1 //===-- MICmdCmdData.cpp ----------------------------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // Overview: CMICmdCmdDataEvaluateExpression implementation.
10 // CMICmdCmdDataDisassemble implementation.
11 // CMICmdCmdDataReadMemoryBytes implementation.
12 // CMICmdCmdDataReadMemory implementation.
13 // CMICmdCmdDataListRegisterNames implementation.
14 // CMICmdCmdDataListRegisterValues implementation.
15 // CMICmdCmdDataListRegisterChanged implementation.
16 // CMICmdCmdDataWriteMemoryBytes implementation.
17 // CMICmdCmdDataWriteMemory implementation.
18 // CMICmdCmdDataInfoLine implementation.
20 // Third Party Headers:
21 #include "lldb/API/SBInstruction.h"
22 #include "lldb/API/SBInstructionList.h"
23 #include "lldb/API/SBStream.h"
24 #include "lldb/API/SBThread.h"
25 #include "llvm/ADT/StringRef.h"
26 #include "llvm/ADT/Twine.h"
31 #include "MICmdArgValConsume.h"
32 #include "MICmdArgValListOfN.h"
33 #include "MICmdArgValNumber.h"
34 #include "MICmdArgValOptionLong.h"
35 #include "MICmdArgValOptionShort.h"
36 #include "MICmdArgValString.h"
37 #include "MICmdArgValThreadGrp.h"
38 #include "MICmdCmdData.h"
39 #include "MICmnLLDBDebugSessionInfo.h"
40 #include "MICmnLLDBDebugSessionInfoVarObj.h"
41 #include "MICmnLLDBDebugger.h"
42 #include "MICmnLLDBProxySBValue.h"
43 #include "MICmnLLDBUtilSBValue.h"
44 #include "MICmnMIResultRecord.h"
45 #include "MICmnMIValueConst.h"
49 CMIUtilString IntToHexAddrStr(uint32_t number) {
50 return CMIUtilString("0x" + llvm::Twine::utohexstr(number).str());
55 // Details: CMICmdCmdDataEvaluateExpression constructor.
61 CMICmdCmdDataEvaluateExpression::CMICmdCmdDataEvaluateExpression()
62 : m_bExpressionValid(true), m_bEvaluatedExpression(true), m_strValue("??"),
63 m_bFoundInvalidChar(false), m_cExpressionInvalidChar(0x00),
64 m_constStrArgExpr("expr") {
65 // Command factory matches this name with that received from the stdin stream
66 m_strMiCmd = "data-evaluate-expression";
68 // Required by the CMICmdFactory when registering *this command
69 m_pSelfCreatorFn = &CMICmdCmdDataEvaluateExpression::CreateSelf;
73 // Details: CMICmdCmdDataEvaluateExpression destructor.
74 // Type: Overrideable.
79 CMICmdCmdDataEvaluateExpression::~CMICmdCmdDataEvaluateExpression() {}
82 // Details: The invoker requires this function. The parses the command line
84 // arguments to extract values for each of those arguments.
87 // Return: MIstatus::success - Functional succeeded.
88 // MIstatus::failure - Functional failed.
91 bool CMICmdCmdDataEvaluateExpression::ParseArgs() {
93 new CMICmdArgValString(m_constStrArgExpr, true, true, true, true));
94 return ParseValidateCmdOptions();
98 // Details: The invoker requires this function. The command does work in this
100 // The command is likely to communicate with the LLDB SBDebugger in
104 // Return: MIstatus::success - Functional succeeded.
105 // MIstatus::failure - Functional failed.
108 bool CMICmdCmdDataEvaluateExpression::Execute() {
109 CMICMDBASE_GETOPTION(pArgExpr, String, m_constStrArgExpr);
111 const CMIUtilString &rExpression(pArgExpr->GetValue());
112 CMICmnLLDBDebugSessionInfo &rSessionInfo(
113 CMICmnLLDBDebugSessionInfo::Instance());
114 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
115 lldb::SBThread thread = sbProcess.GetSelectedThread();
116 m_bExpressionValid = (thread.GetNumFrames() > 0);
117 if (!m_bExpressionValid)
118 return MIstatus::success;
120 lldb::SBFrame frame = thread.GetSelectedFrame();
121 lldb::SBValue value = frame.EvaluateExpression(rExpression.c_str());
122 m_Error = value.GetError();
123 if (!value.IsValid() || m_Error.Fail())
124 value = frame.FindVariable(rExpression.c_str());
125 const CMICmnLLDBUtilSBValue utilValue(value, true);
126 if (!utilValue.IsValid() || utilValue.IsValueUnknown()) {
127 m_bEvaluatedExpression = false;
128 return MIstatus::success;
130 if (!utilValue.HasName()) {
131 if (HaveInvalidCharacterInExpression(rExpression,
132 m_cExpressionInvalidChar)) {
133 m_bFoundInvalidChar = true;
134 return MIstatus::success;
137 m_strValue = rExpression;
138 return MIstatus::success;
140 if (rExpression.IsQuoted()) {
141 m_strValue = rExpression.Trim('\"');
142 return MIstatus::success;
144 m_strValue = utilValue.GetValue(true).Escape().AddSlashes();
145 return MIstatus::success;
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 // Details: Required by the CMICmdFactory when registering *this command. The
205 // calls this function to create an instance of *this command.
206 // Type: Static method.
208 // Return: CMICmdBase * - Pointer to a new command.
211 CMICmdBase *CMICmdCmdDataEvaluateExpression::CreateSelf() {
212 return new CMICmdCmdDataEvaluateExpression();
216 // Details: Examine the expression string to see if it contains invalid
219 // Args: vrExpr - (R) Expression string given to *this command.
220 // vrwInvalidChar - (W) True = Invalid character found, false =
222 // Return: bool - True = Invalid character found, false = nothing found.
225 bool CMICmdCmdDataEvaluateExpression::HaveInvalidCharacterInExpression(
226 const CMIUtilString &vrExpr, char &vrwInvalidChar) {
227 static const std::string strInvalidCharacters(";#\\");
228 const size_t nInvalidCharacterOffset =
229 vrExpr.find_first_of(strInvalidCharacters);
230 const bool bFoundInvalidCharInExpression =
231 (nInvalidCharacterOffset != CMIUtilString::npos);
233 bFoundInvalidCharInExpression ? vrExpr[nInvalidCharacterOffset] : 0x00;
234 return bFoundInvalidCharInExpression;
239 // Details: CMICmdCmdDataDisassemble constructor.
245 CMICmdCmdDataDisassemble::CMICmdCmdDataDisassemble()
246 : m_constStrArgAddrStart("s"), m_constStrArgAddrEnd("e"),
247 m_constStrArgMode("mode"), m_miValueList(true) {
248 // Command factory matches this name with that received from the stdin stream
249 m_strMiCmd = "data-disassemble";
251 // Required by the CMICmdFactory when registering *this command
252 m_pSelfCreatorFn = &CMICmdCmdDataDisassemble::CreateSelf;
256 // Details: CMICmdCmdDataDisassemble destructor.
257 // Type: Overrideable.
262 CMICmdCmdDataDisassemble::~CMICmdCmdDataDisassemble() {}
265 // Details: The invoker requires this function. The parses the command line
267 // arguments to extract values for each of those arguments.
270 // Return: MIstatus::success - Functional succeeded.
271 // MIstatus::failure - Functional failed.
274 bool CMICmdCmdDataDisassemble::ParseArgs() {
275 m_setCmdArgs.Add(new CMICmdArgValOptionShort(
276 m_constStrArgAddrStart, true, true,
277 CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1));
278 m_setCmdArgs.Add(new CMICmdArgValOptionShort(
279 m_constStrArgAddrEnd, true, true,
280 CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1));
281 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgMode, true, true));
282 return ParseValidateCmdOptions();
286 // Details: The invoker requires this function. The command does work in this
288 // The command is likely to communicate with the LLDB SBDebugger in
292 // Return: MIstatus::success - Functional succeeded.
293 // MIstatus::failure - Functional failed.
296 bool CMICmdCmdDataDisassemble::Execute() {
297 CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
298 CMICMDBASE_GETOPTION(pArgAddrStart, OptionShort, m_constStrArgAddrStart);
299 CMICMDBASE_GETOPTION(pArgAddrEnd, OptionShort, m_constStrArgAddrEnd);
300 CMICMDBASE_GETOPTION(pArgMode, Number, m_constStrArgMode);
302 // Retrieve the --thread option's thread ID (only 1)
303 MIuint64 nThreadId = UINT64_MAX;
304 if (pArgThread->GetFound() &&
305 !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) {
306 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID),
307 m_cmdData.strMiCmd.c_str(),
308 m_constStrArgThread.c_str()));
309 return MIstatus::failure;
311 CMIUtilString strAddrStart;
312 if (!pArgAddrStart->GetExpectedOption<CMICmdArgValString, CMIUtilString>(
314 SetError(CMIUtilString::Format(
315 MIRSRC(IDS_CMD_ERR_DISASM_ADDR_START_INVALID),
316 m_cmdData.strMiCmd.c_str(), m_constStrArgAddrStart.c_str()));
317 return MIstatus::failure;
319 MIint64 nAddrStart = 0;
320 if (!strAddrStart.ExtractNumber(nAddrStart)) {
321 SetError(CMIUtilString::Format(
322 MIRSRC(IDS_CMD_ERR_DISASM_ADDR_START_INVALID),
323 m_cmdData.strMiCmd.c_str(), m_constStrArgAddrStart.c_str()));
324 return MIstatus::failure;
327 CMIUtilString strAddrEnd;
328 if (!pArgAddrEnd->GetExpectedOption<CMICmdArgValString, CMIUtilString>(
330 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_END_INVALID),
331 m_cmdData.strMiCmd.c_str(),
332 m_constStrArgAddrEnd.c_str()));
333 return MIstatus::failure;
335 MIint64 nAddrEnd = 0;
336 if (!strAddrEnd.ExtractNumber(nAddrEnd)) {
337 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_END_INVALID),
338 m_cmdData.strMiCmd.c_str(),
339 m_constStrArgAddrEnd.c_str()));
340 return MIstatus::failure;
342 const MIuint nDisasmMode = pArgMode->GetValue();
344 CMICmnLLDBDebugSessionInfo &rSessionInfo(
345 CMICmnLLDBDebugSessionInfo::Instance());
346 lldb::SBTarget sbTarget = rSessionInfo.GetTarget();
347 lldb::addr_t lldbStartAddr = static_cast<lldb::addr_t>(nAddrStart);
348 lldb::SBInstructionList instructions = sbTarget.ReadInstructions(
349 lldb::SBAddress(lldbStartAddr, sbTarget), nAddrEnd - nAddrStart);
350 const MIuint nInstructions = instructions.GetSize();
351 // Calculate the offset of first instruction so that we can generate offset
353 lldb::addr_t start_offset = 0;
354 if (nInstructions > 0)
356 instructions.GetInstructionAtIndex(0).GetAddress().GetOffset();
358 for (size_t i = 0; i < nInstructions; i++) {
359 const char *pUnknown = "??";
360 lldb::SBInstruction instrt = instructions.GetInstructionAtIndex(i);
361 const char *pStrMnemonic = instrt.GetMnemonic(sbTarget);
362 pStrMnemonic = (pStrMnemonic != nullptr) ? pStrMnemonic : pUnknown;
363 const char *pStrComment = instrt.GetComment(sbTarget);
364 CMIUtilString strComment;
365 if (pStrComment != nullptr && *pStrComment != '\0')
366 strComment = CMIUtilString::Format("; %s", pStrComment);
367 lldb::SBAddress address = instrt.GetAddress();
368 lldb::addr_t addr = address.GetLoadAddress(sbTarget);
369 const char *pFnName = address.GetFunction().GetName();
370 pFnName = (pFnName != nullptr) ? pFnName : pUnknown;
371 lldb::addr_t addrOffSet = address.GetOffset() - start_offset;
372 const char *pStrOperands = instrt.GetOperands(sbTarget);
373 pStrOperands = (pStrOperands != nullptr) ? pStrOperands : pUnknown;
374 const size_t instrtSize = instrt.GetByteSize();
376 // MI "{address=\"0x%016" PRIx64
377 // "\",func-name=\"%s\",offset=\"%lld\",inst=\"%s %s\"}"
378 const CMICmnMIValueConst miValueConst(
379 CMIUtilString::Format("0x%016" PRIx64, addr));
380 const CMICmnMIValueResult miValueResult("address", miValueConst);
381 CMICmnMIValueTuple miValueTuple(miValueResult);
382 const CMICmnMIValueConst miValueConst2(pFnName);
383 const CMICmnMIValueResult miValueResult2("func-name", miValueConst2);
384 miValueTuple.Add(miValueResult2);
385 const CMICmnMIValueConst miValueConst3(
386 CMIUtilString::Format("%lld", addrOffSet));
387 const CMICmnMIValueResult miValueResult3("offset", miValueConst3);
388 miValueTuple.Add(miValueResult3);
389 const CMICmnMIValueConst miValueConst4(
390 CMIUtilString::Format("%d", instrtSize));
391 const CMICmnMIValueResult miValueResult4("size", miValueConst4);
392 miValueTuple.Add(miValueResult4);
393 const CMICmnMIValueConst miValueConst5(
394 CMIUtilString::Format("%s %s%s", pStrMnemonic, pStrOperands,
395 strComment.Escape(true).c_str()));
396 const CMICmnMIValueResult miValueResult5("inst", miValueConst5);
397 miValueTuple.Add(miValueResult5);
399 if (nDisasmMode == 1) {
400 lldb::SBLineEntry lineEntry = address.GetLineEntry();
401 const MIuint nLine = lineEntry.GetLine();
402 const char *pFileName = lineEntry.GetFileSpec().GetFilename();
403 pFileName = (pFileName != nullptr) ? pFileName : pUnknown;
404 // Get a full path to the file.
405 char pathBuffer[PATH_MAX];
406 lineEntry.GetFileSpec().GetPath(pathBuffer, PATH_MAX);
408 // MI "src_and_asm_line={line=\"%u\",file=\"%s\",line_asm_insn=[ ],
410 const CMICmnMIValueConst miValueConst(
411 CMIUtilString::Format("%u", nLine));
412 const CMICmnMIValueResult miValueResult("line", miValueConst);
413 CMICmnMIValueTuple miValueTuple2(miValueResult);
414 const CMICmnMIValueConst miValueConst2(pFileName);
415 const CMICmnMIValueResult miValueResult2("file", miValueConst2);
416 miValueTuple2.Add(miValueResult2);
417 const CMICmnMIValueList miValueList(miValueTuple);
418 const CMICmnMIValueResult miValueResult3("line_asm_insn", miValueList);
419 miValueTuple2.Add(miValueResult3);
420 const CMICmnMIValueConst miValueConst5(pathBuffer);
421 const CMICmnMIValueResult miValueResult5("fullname", miValueConst5);
422 miValueTuple2.Add(miValueResult5);
423 const CMICmnMIValueResult miValueResult4("src_and_asm_line",
425 m_miValueList.Add(miValueResult4);
427 m_miValueList.Add(miValueTuple);
431 return MIstatus::success;
435 // Details: The invoker requires this function. The command prepares a MI Record
437 // for the work carried out in the Execute().
440 // Return: MIstatus::success - Functional succeeded.
441 // MIstatus::failure - Functional failed.
444 bool CMICmdCmdDataDisassemble::Acknowledge() {
445 const CMICmnMIValueResult miValueResult("asm_insns", m_miValueList);
446 const CMICmnMIResultRecord miRecordResult(
447 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
449 m_miResultRecord = miRecordResult;
451 return MIstatus::success;
455 // Details: Required by the CMICmdFactory when registering *this command. The
457 // calls this function to create an instance of *this command.
458 // Type: Static method.
460 // Return: CMICmdBase * - Pointer to a new command.
463 CMICmdBase *CMICmdCmdDataDisassemble::CreateSelf() {
464 return new CMICmdCmdDataDisassemble();
469 // Details: CMICmdCmdDataReadMemoryBytes constructor.
475 CMICmdCmdDataReadMemoryBytes::CMICmdCmdDataReadMemoryBytes()
476 : m_constStrArgByteOffset("o"), m_constStrArgAddrExpr("address"),
477 m_constStrArgNumBytes("count"), m_pBufferMemory(nullptr), m_nAddrStart(0),
478 m_nAddrNumBytesToRead(0) {
479 // Command factory matches this name with that received from the stdin stream
480 m_strMiCmd = "data-read-memory-bytes";
482 // Required by the CMICmdFactory when registering *this command
483 m_pSelfCreatorFn = &CMICmdCmdDataReadMemoryBytes::CreateSelf;
487 // Details: CMICmdCmdDataReadMemoryBytes destructor.
488 // Type: Overrideable.
493 CMICmdCmdDataReadMemoryBytes::~CMICmdCmdDataReadMemoryBytes() {
494 if (m_pBufferMemory != nullptr) {
495 delete[] m_pBufferMemory;
496 m_pBufferMemory = nullptr;
501 // Details: The invoker requires this function. The parses the command line
503 // arguments to extract values for each of those arguments.
506 // Return: MIstatus::success - Functional succeeded.
507 // MIstatus::failure - Functional failed.
510 bool CMICmdCmdDataReadMemoryBytes::ParseArgs() {
512 new CMICmdArgValOptionShort(m_constStrArgByteOffset, false, true,
513 CMICmdArgValListBase::eArgValType_Number, 1));
515 new CMICmdArgValString(m_constStrArgAddrExpr, true, true, true, true));
516 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumBytes, true, true));
517 return ParseValidateCmdOptions();
521 // Details: The invoker requires this function. The command does work in this
523 // The command is likely to communicate with the LLDB SBDebugger in
527 // Return: MIstatus::success - Function succeeded.
528 // MIstatus::failure - Function failed.
531 bool CMICmdCmdDataReadMemoryBytes::Execute() {
532 CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread);
533 CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame);
534 CMICMDBASE_GETOPTION(pArgAddrOffset, OptionShort, m_constStrArgByteOffset);
535 CMICMDBASE_GETOPTION(pArgAddrExpr, String, m_constStrArgAddrExpr);
536 CMICMDBASE_GETOPTION(pArgNumBytes, Number, m_constStrArgNumBytes);
538 // get the --thread option value
539 MIuint64 nThreadId = UINT64_MAX;
540 if (pArgThread->GetFound() &&
541 !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) {
542 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
543 m_cmdData.strMiCmd.c_str(),
544 m_constStrArgThread.c_str()));
545 return MIstatus::failure;
548 // get the --frame option value
549 MIuint64 nFrame = UINT64_MAX;
550 if (pArgFrame->GetFound() &&
551 !pArgFrame->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nFrame)) {
552 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
553 m_cmdData.strMiCmd.c_str(),
554 m_constStrArgFrame.c_str()));
555 return MIstatus::failure;
558 // get the -o option value
559 MIuint64 nAddrOffset = 0;
560 if (pArgAddrOffset->GetFound() &&
561 !pArgAddrOffset->GetExpectedOption<CMICmdArgValNumber, MIuint64>(
563 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND),
564 m_cmdData.strMiCmd.c_str(),
565 m_constStrArgByteOffset.c_str()));
566 return MIstatus::failure;
569 CMICmnLLDBDebugSessionInfo &rSessionInfo(
570 CMICmnLLDBDebugSessionInfo::Instance());
571 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
572 if (!sbProcess.IsValid()) {
573 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS),
574 m_cmdData.strMiCmd.c_str()));
575 return MIstatus::failure;
578 lldb::SBThread thread = (nThreadId != UINT64_MAX)
579 ? sbProcess.GetThreadByIndexID(nThreadId)
580 : sbProcess.GetSelectedThread();
581 if (!thread.IsValid()) {
582 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID),
583 m_cmdData.strMiCmd.c_str()));
584 return MIstatus::failure;
587 lldb::SBFrame frame = (nFrame != UINT64_MAX) ? thread.GetFrameAtIndex(nFrame)
588 : thread.GetSelectedFrame();
589 if (!frame.IsValid()) {
590 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FRAME_INVALID),
591 m_cmdData.strMiCmd.c_str()));
592 return MIstatus::failure;
595 const CMIUtilString &rAddrExpr = pArgAddrExpr->GetValue();
596 lldb::SBValue addrExprValue = frame.EvaluateExpression(rAddrExpr.c_str());
597 lldb::SBError error = addrExprValue.GetError();
599 SetError(error.GetCString());
600 return MIstatus::failure;
601 } else if (!addrExprValue.IsValid()) {
602 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_EXPR_INVALID),
604 return MIstatus::failure;
607 MIuint64 nAddrStart = 0;
608 if (!CMICmnLLDBProxySBValue::GetValueAsUnsigned(addrExprValue, nAddrStart)) {
609 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_EXPR_INVALID),
611 return MIstatus::failure;
614 nAddrStart += nAddrOffset;
615 const MIuint64 nAddrNumBytes = pArgNumBytes->GetValue();
617 m_pBufferMemory = new unsigned char[nAddrNumBytes];
618 if (m_pBufferMemory == nullptr) {
619 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_MEMORY_ALLOC_FAILURE),
620 m_cmdData.strMiCmd.c_str(), nAddrNumBytes));
621 return MIstatus::failure;
624 const MIuint64 nReadBytes =
625 sbProcess.ReadMemory(static_cast<lldb::addr_t>(nAddrStart),
626 (void *)m_pBufferMemory, nAddrNumBytes, error);
627 if (nReadBytes != nAddrNumBytes) {
628 SetError(CMIUtilString::Format(
629 MIRSRC(IDS_CMD_ERR_LLDB_ERR_NOT_READ_WHOLE_BLK),
630 m_cmdData.strMiCmd.c_str(), nAddrNumBytes, nAddrStart));
631 return MIstatus::failure;
635 const bool bOk = error.GetDescription(err);
637 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES),
638 m_cmdData.strMiCmd.c_str(), nAddrNumBytes,
639 nAddrStart, err.GetData()));
640 return MIstatus::failure;
643 m_nAddrStart = nAddrStart;
644 m_nAddrNumBytesToRead = nAddrNumBytes;
646 return MIstatus::success;
650 // Details: The invoker requires this function. The command prepares a MI Record
652 // for the work carried out in the Execute().
655 // Return: MIstatus::success - Functional succeeded.
656 // MIstatus::failure - Functional failed.
659 bool CMICmdCmdDataReadMemoryBytes::Acknowledge() {
660 // MI: memory=[{begin=\"0x%016" PRIx64 "\",offset=\"0x%016" PRIx64"
661 // \",end=\"0x%016" PRIx64 "\",contents=\" \" }]"
662 const CMICmnMIValueConst miValueConst(
663 CMIUtilString::Format("0x%016" PRIx64, m_nAddrStart));
664 const CMICmnMIValueResult miValueResult("begin", miValueConst);
665 CMICmnMIValueTuple miValueTuple(miValueResult);
666 const MIuint64 nAddrOffset = 0;
667 const CMICmnMIValueConst miValueConst2(
668 CMIUtilString::Format("0x%016" PRIx64, nAddrOffset));
669 const CMICmnMIValueResult miValueResult2("offset", miValueConst2);
670 miValueTuple.Add(miValueResult2);
671 const CMICmnMIValueConst miValueConst3(CMIUtilString::Format(
672 "0x%016" PRIx64, m_nAddrStart + m_nAddrNumBytesToRead));
673 const CMICmnMIValueResult miValueResult3("end", miValueConst3);
674 miValueTuple.Add(miValueResult3);
676 // MI: contents=\" \"
677 CMIUtilString strContent;
678 strContent.reserve((m_nAddrNumBytesToRead << 1) + 1);
679 for (MIuint64 i = 0; i < m_nAddrNumBytesToRead; i++) {
680 strContent += CMIUtilString::Format("%02hhx", m_pBufferMemory[i]);
682 const CMICmnMIValueConst miValueConst4(strContent);
683 const CMICmnMIValueResult miValueResult4("contents", miValueConst4);
684 miValueTuple.Add(miValueResult4);
685 const CMICmnMIValueList miValueList(miValueTuple);
686 const CMICmnMIValueResult miValueResult5("memory", miValueList);
688 const CMICmnMIResultRecord miRecordResult(
689 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
691 m_miResultRecord = miRecordResult;
693 return MIstatus::success;
697 // Details: Required by the CMICmdFactory when registering *this command. The
699 // calls this function to create an instance of *this command.
700 // Type: Static method.
702 // Return: CMICmdBase * - Pointer to a new command.
705 CMICmdBase *CMICmdCmdDataReadMemoryBytes::CreateSelf() {
706 return new CMICmdCmdDataReadMemoryBytes();
711 // Details: CMICmdCmdDataReadMemory constructor.
717 CMICmdCmdDataReadMemory::CMICmdCmdDataReadMemory() {
718 // Command factory matches this name with that received from the stdin stream
719 m_strMiCmd = "data-read-memory";
721 // Required by the CMICmdFactory when registering *this command
722 m_pSelfCreatorFn = &CMICmdCmdDataReadMemory::CreateSelf;
726 // Details: CMICmdCmdDataReadMemory destructor.
727 // Type: Overrideable.
732 CMICmdCmdDataReadMemory::~CMICmdCmdDataReadMemory() {}
735 // Details: The invoker requires this function. The command does work in this
737 // The command is likely to communicate with the LLDB SBDebugger in
741 // Return: MIstatus::success - Functional succeeded.
742 // MIstatus::failure - Functional failed.
745 bool CMICmdCmdDataReadMemory::Execute() {
746 // Do nothing - command deprecated use "data-read-memory-bytes" command
747 return MIstatus::success;
751 // Details: The invoker requires this function. The command prepares a MI Record
753 // for the work carried out in the Execute().
756 // Return: MIstatus::success - Functional succeeded.
757 // MIstatus::failure - Functional failed.
760 bool CMICmdCmdDataReadMemory::Acknowledge() {
761 // Command CMICmdCmdSupportListFeatures sends "data-read-memory-bytes" which
762 // causes this command not to be called
763 const CMICmnMIValueConst miValueConst(
764 MIRSRC(IDS_CMD_ERR_NOT_IMPLEMENTED_DEPRECATED));
765 const CMICmnMIValueResult miValueResult("msg", miValueConst);
766 const CMICmnMIResultRecord miRecordResult(
767 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
769 m_miResultRecord = miRecordResult;
771 return MIstatus::success;
775 // Details: Required by the CMICmdFactory when registering *this command. The
777 // calls this function to create an instance of *this command.
778 // Type: Static method.
780 // Return: CMICmdBase * - Pointer to a new command.
783 CMICmdBase *CMICmdCmdDataReadMemory::CreateSelf() {
784 return new CMICmdCmdDataReadMemory();
789 // Details: CMICmdCmdDataListRegisterNames constructor.
795 CMICmdCmdDataListRegisterNames::CMICmdCmdDataListRegisterNames()
796 : m_constStrArgRegNo("regno"), m_miValueList(true) {
797 // Command factory matches this name with that received from the stdin stream
798 m_strMiCmd = "data-list-register-names";
800 // Required by the CMICmdFactory when registering *this command
801 m_pSelfCreatorFn = &CMICmdCmdDataListRegisterNames::CreateSelf;
805 // Details: CMICmdCmdDataReadMemoryBytes destructor.
806 // Type: Overrideable.
811 CMICmdCmdDataListRegisterNames::~CMICmdCmdDataListRegisterNames() {}
814 // Details: The invoker requires this function. The parses the command line
816 // arguments to extract values for each of those arguments.
819 // Return: MIstatus::success - Functional succeeded.
820 // MIstatus::failure - Functional failed.
823 bool CMICmdCmdDataListRegisterNames::ParseArgs() {
825 new CMICmdArgValListOfN(m_constStrArgRegNo, false, false,
826 CMICmdArgValListBase::eArgValType_Number));
827 return ParseValidateCmdOptions();
831 // Details: The invoker requires this function. The command does work in this
833 // The command is likely to communicate with the LLDB SBDebugger in
837 // Return: MIstatus::success - Functional succeeded.
838 // MIstatus::failure - Functional failed.
841 bool CMICmdCmdDataListRegisterNames::Execute() {
842 CMICMDBASE_GETOPTION(pArgRegNo, ListOfN, m_constStrArgRegNo);
844 CMICmnLLDBDebugSessionInfo &rSessionInfo(
845 CMICmnLLDBDebugSessionInfo::Instance());
846 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
847 if (!sbProcess.IsValid()) {
848 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS),
849 m_cmdData.strMiCmd.c_str()));
850 return MIstatus::failure;
853 const CMICmdArgValListBase::VecArgObjPtr_t &rVecRegNo(
854 pArgRegNo->GetExpectedOptions());
855 if (!rVecRegNo.empty()) {
856 // List of required registers
857 CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecRegNo.begin();
858 while (it != rVecRegNo.end()) {
859 const CMICmdArgValNumber *pRegNo = static_cast<CMICmdArgValNumber *>(*it);
860 const MIuint nRegIndex = pRegNo->GetValue();
861 lldb::SBValue regValue = GetRegister(nRegIndex);
862 if (regValue.IsValid()) {
863 const CMICmnMIValueConst miValueConst(
864 CMICmnLLDBUtilSBValue(regValue).GetName());
865 m_miValueList.Add(miValueConst);
872 // List of all registers
873 lldb::SBThread thread = sbProcess.GetSelectedThread();
874 lldb::SBFrame frame = thread.GetSelectedFrame();
875 lldb::SBValueList registers = frame.GetRegisters();
876 const MIuint nRegisters = registers.GetSize();
877 for (MIuint i = 0; i < nRegisters; i++) {
878 lldb::SBValue value = registers.GetValueAtIndex(i);
879 const MIuint nRegChildren = value.GetNumChildren();
880 for (MIuint j = 0; j < nRegChildren; j++) {
881 lldb::SBValue regValue = value.GetChildAtIndex(j);
882 if (regValue.IsValid()) {
883 const CMICmnMIValueConst miValueConst(
884 CMICmnLLDBUtilSBValue(regValue).GetName());
885 m_miValueList.Add(miValueConst);
891 return MIstatus::success;
895 // Details: The invoker requires this function. The command prepares a MI Record
897 // for the work carried out in the Execute().
900 // Return: MIstatus::success - Functional succeeded.
901 // MIstatus::failure - Functional failed.
904 bool CMICmdCmdDataListRegisterNames::Acknowledge() {
905 const CMICmnMIValueResult miValueResult("register-names", m_miValueList);
906 const CMICmnMIResultRecord miRecordResult(
907 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
909 m_miResultRecord = miRecordResult;
911 return MIstatus::success;
915 // Details: Required by the CMICmdFactory when registering *this command. The
917 // calls this function to create an instance of *this command.
918 // Type: Static method.
920 // Return: CMICmdBase * - Pointer to a new command.
923 CMICmdBase *CMICmdCmdDataListRegisterNames::CreateSelf() {
924 return new CMICmdCmdDataListRegisterNames();
928 // Details: Required by the CMICmdFactory when registering *this command. The
930 // calls this function to create an instance of *this command.
933 // Return: lldb::SBValue - LLDB SBValue object.
937 CMICmdCmdDataListRegisterNames::GetRegister(const MIuint vRegisterIndex) const {
938 lldb::SBThread thread =
939 CMICmnLLDBDebugSessionInfo::Instance().GetProcess().GetSelectedThread();
940 lldb::SBFrame frame = thread.GetSelectedFrame();
941 lldb::SBValueList registers = frame.GetRegisters();
942 const MIuint nRegisters = registers.GetSize();
943 MIuint nRegisterIndex(vRegisterIndex);
944 for (MIuint i = 0; i < nRegisters; i++) {
945 lldb::SBValue value = registers.GetValueAtIndex(i);
946 const MIuint nRegChildren = value.GetNumChildren();
947 if (nRegisterIndex >= nRegChildren) {
948 nRegisterIndex -= nRegChildren;
952 lldb::SBValue value2 = value.GetChildAtIndex(nRegisterIndex);
953 if (value2.IsValid()) {
958 return lldb::SBValue();
963 // Details: CMICmdCmdDataListRegisterValues constructor.
969 CMICmdCmdDataListRegisterValues::CMICmdCmdDataListRegisterValues()
970 : m_constStrArgSkip("skip-unavailable"), m_constStrArgFormat("fmt"),
971 m_constStrArgRegNo("regno"), m_miValueList(true) {
972 // Command factory matches this name with that received from the stdin stream
973 m_strMiCmd = "data-list-register-values";
975 // Required by the CMICmdFactory when registering *this command
976 m_pSelfCreatorFn = &CMICmdCmdDataListRegisterValues::CreateSelf;
980 // Details: CMICmdCmdDataListRegisterValues destructor.
981 // Type: Overrideable.
986 CMICmdCmdDataListRegisterValues::~CMICmdCmdDataListRegisterValues() {}
989 // Details: The invoker requires this function. The parses the command line
991 // arguments to extract values for each of those arguments.
994 // Return: MIstatus::success - Functional succeeded.
995 // MIstatus::failure - Functional failed.
998 bool CMICmdCmdDataListRegisterValues::ParseArgs() {
1000 new CMICmdArgValOptionLong(m_constStrArgThread, false, false,
1001 CMICmdArgValListBase::eArgValType_Number, 1));
1002 m_setCmdArgs.Add(new CMICmdArgValOptionLong(m_constStrArgSkip, false, false));
1003 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgFormat, true, true));
1005 new CMICmdArgValListOfN(m_constStrArgRegNo, false, true,
1006 CMICmdArgValListBase::eArgValType_Number));
1007 return ParseValidateCmdOptions();
1011 // Details: The invoker requires this function. The command does work in this
1013 // The command is likely to communicate with the LLDB SBDebugger in
1015 // Type: Overridden.
1017 // Return: MIstatus::success - Functional succeeded.
1018 // MIstatus::failure - Functional failed.
1021 bool CMICmdCmdDataListRegisterValues::Execute() {
1022 CMICMDBASE_GETOPTION(pArgFormat, String, m_constStrArgFormat);
1023 CMICMDBASE_GETOPTION(pArgRegNo, ListOfN, m_constStrArgRegNo);
1025 const CMIUtilString &rStrFormat(pArgFormat->GetValue());
1026 if (rStrFormat.length() != 1) {
1027 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_FORMAT_TYPE),
1028 m_cmdData.strMiCmd.c_str(),
1029 rStrFormat.c_str()));
1030 return MIstatus::failure;
1032 const CMICmnLLDBDebugSessionInfoVarObj::varFormat_e eFormat =
1033 CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForChar(rStrFormat[0]);
1034 if (eFormat == CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid) {
1035 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_FORMAT_TYPE),
1036 m_cmdData.strMiCmd.c_str(),
1037 rStrFormat.c_str()));
1038 return MIstatus::failure;
1041 CMICmnLLDBDebugSessionInfo &rSessionInfo(
1042 CMICmnLLDBDebugSessionInfo::Instance());
1043 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
1044 if (!sbProcess.IsValid()) {
1045 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS),
1046 m_cmdData.strMiCmd.c_str()));
1047 return MIstatus::failure;
1050 const CMICmdArgValListBase::VecArgObjPtr_t &rVecRegNo(
1051 pArgRegNo->GetExpectedOptions());
1052 if (!rVecRegNo.empty()) {
1053 // List of required registers
1054 CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecRegNo.begin();
1055 while (it != rVecRegNo.end()) {
1056 const CMICmdArgValNumber *pRegNo = static_cast<CMICmdArgValNumber *>(*it);
1057 const MIuint nRegIndex = pRegNo->GetValue();
1058 lldb::SBValue regValue = GetRegister(nRegIndex);
1059 if (regValue.IsValid()) {
1060 AddToOutput(nRegIndex, regValue, eFormat);
1067 // No register numbers are provided. Output all registers.
1068 lldb::SBThread thread = sbProcess.GetSelectedThread();
1069 lldb::SBFrame frame = thread.GetSelectedFrame();
1070 lldb::SBValueList registers = frame.GetRegisters();
1071 const MIuint nRegisters = registers.GetSize();
1072 MIuint nRegIndex = 0;
1073 for (MIuint i = 0; i < nRegisters; i++) {
1074 lldb::SBValue value = registers.GetValueAtIndex(i);
1075 const MIuint nRegChildren = value.GetNumChildren();
1076 for (MIuint j = 0; j < nRegChildren; j++) {
1077 lldb::SBValue regValue = value.GetChildAtIndex(j);
1078 if (regValue.IsValid()) {
1079 AddToOutput(nRegIndex, regValue, eFormat);
1088 return MIstatus::success;
1092 // Details: The invoker requires this function. The command prepares a MI Record
1094 // for the work carried out in the Execute().
1095 // Type: Overridden.
1097 // Return: MIstatus::success - Functional succeeded.
1098 // MIstatus::failure - Functional failed.
1101 bool CMICmdCmdDataListRegisterValues::Acknowledge() {
1102 const CMICmnMIValueResult miValueResult("register-values", m_miValueList);
1103 const CMICmnMIResultRecord miRecordResult(
1104 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done,
1106 m_miResultRecord = miRecordResult;
1108 return MIstatus::success;
1112 // Details: Required by the CMICmdFactory when registering *this command. The
1114 // calls this function to create an instance of *this command.
1115 // Type: Static method.
1117 // Return: CMICmdBase * - Pointer to a new command.
1120 CMICmdBase *CMICmdCmdDataListRegisterValues::CreateSelf() {
1121 return new CMICmdCmdDataListRegisterValues();
1125 // Details: Required by the CMICmdFactory when registering *this command. The
1127 // calls this function to create an instance of *this command.
1130 // Return: lldb::SBValue - LLDB SBValue object.
1133 lldb::SBValue CMICmdCmdDataListRegisterValues::GetRegister(
1134 const MIuint vRegisterIndex) const {
1135 lldb::SBThread thread =
1136 CMICmnLLDBDebugSessionInfo::Instance().GetProcess().GetSelectedThread();
1137 lldb::SBFrame frame = thread.GetSelectedFrame();
1138 lldb::SBValueList registers = frame.GetRegisters();
1139 const MIuint nRegisters = registers.GetSize();
1140 MIuint nRegisterIndex(vRegisterIndex);
1141 for (MIuint i = 0; i < nRegisters; i++) {
1142 lldb::SBValue value = registers.GetValueAtIndex(i);
1143 const MIuint nRegChildren = value.GetNumChildren();
1144 if (nRegisterIndex >= nRegChildren) {
1145 nRegisterIndex -= nRegChildren;
1149 lldb::SBValue value2 = value.GetChildAtIndex(nRegisterIndex);
1150 if (value2.IsValid()) {
1155 return lldb::SBValue();
1159 // Details: Adds the register value to the output list.
1161 // Args: Value of the register, its index and output format.
1165 void CMICmdCmdDataListRegisterValues::AddToOutput(
1166 const MIuint vnIndex, const lldb::SBValue &vrValue,
1167 CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat) {
1168 const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%u", vnIndex));
1169 const CMICmnMIValueResult miValueResult("number", miValueConst);
1170 CMICmnMIValueTuple miValueTuple(miValueResult);
1171 const CMIUtilString strRegValue(
1172 CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(vrValue,
1174 const CMICmnMIValueConst miValueConst2(strRegValue);
1175 const CMICmnMIValueResult miValueResult2("value", miValueConst2);
1176 miValueTuple.Add(miValueResult2);
1177 m_miValueList.Add(miValueTuple);
1182 // Details: CMICmdCmdDataListRegisterChanged constructor.
1188 CMICmdCmdDataListRegisterChanged::CMICmdCmdDataListRegisterChanged() {
1189 // Command factory matches this name with that received from the stdin stream
1190 m_strMiCmd = "data-list-changed-registers";
1192 // Required by the CMICmdFactory when registering *this command
1193 m_pSelfCreatorFn = &CMICmdCmdDataListRegisterChanged::CreateSelf;
1197 // Details: CMICmdCmdDataListRegisterChanged destructor.
1198 // Type: Overrideable.
1203 CMICmdCmdDataListRegisterChanged::~CMICmdCmdDataListRegisterChanged() {}
1206 // Details: The invoker requires this function. The command does work in this
1208 // The command is likely to communicate with the LLDB SBDebugger in
1210 // Type: Overridden.
1212 // Return: MIstatus::success - Functional succeeded.
1213 // MIstatus::failure - Functional failed.
1216 bool CMICmdCmdDataListRegisterChanged::Execute() {
1219 return MIstatus::success;
1223 // Details: The invoker requires this function. The command prepares a MI Record
1225 // for the work carried out in the Execute().
1226 // Type: Overridden.
1228 // Return: MIstatus::success - Functional succeeded.
1229 // MIstatus::failure - Functional failed.
1232 bool CMICmdCmdDataListRegisterChanged::Acknowledge() {
1233 const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED));
1234 const CMICmnMIValueResult miValueResult("msg", miValueConst);
1235 const CMICmnMIResultRecord miRecordResult(
1236 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
1238 m_miResultRecord = miRecordResult;
1240 return MIstatus::success;
1244 // Details: Required by the CMICmdFactory when registering *this command. The
1246 // calls this function to create an instance of *this command.
1247 // Type: Static method.
1249 // Return: CMICmdBase * - Pointer to a new command.
1252 CMICmdBase *CMICmdCmdDataListRegisterChanged::CreateSelf() {
1253 return new CMICmdCmdDataListRegisterChanged();
1258 // Details: CMICmdCmdDataWriteMemoryBytes constructor.
1264 CMICmdCmdDataWriteMemoryBytes::CMICmdCmdDataWriteMemoryBytes()
1265 : m_constStrArgAddr("address"), m_constStrArgContents("contents"),
1266 m_constStrArgCount("count") {
1267 // Command factory matches this name with that received from the stdin stream
1268 m_strMiCmd = "data-write-memory-bytes";
1270 // Required by the CMICmdFactory when registering *this command
1271 m_pSelfCreatorFn = &CMICmdCmdDataWriteMemoryBytes::CreateSelf;
1275 // Details: CMICmdCmdDataWriteMemoryBytes destructor.
1276 // Type: Overrideable.
1281 CMICmdCmdDataWriteMemoryBytes::~CMICmdCmdDataWriteMemoryBytes() {}
1284 // Details: The invoker requires this function. The parses the command line
1286 // arguments to extract values for each of those arguments.
1287 // Type: Overridden.
1289 // Return: MIstatus::success - Functional succeeded.
1290 // MIstatus::failure - Functional failed.
1293 bool CMICmdCmdDataWriteMemoryBytes::ParseArgs() {
1295 new CMICmdArgValString(m_constStrArgAddr, true, true, false, true));
1297 new CMICmdArgValString(m_constStrArgContents, true, true, true, true));
1299 new CMICmdArgValString(m_constStrArgCount, false, true, false, true));
1300 return ParseValidateCmdOptions();
1304 // Details: The invoker requires this function. The command does work in this
1306 // The command is likely to communicate with the LLDB SBDebugger in
1308 // Type: Overridden.
1310 // Return: MIstatus::success - Functional succeeded.
1311 // MIstatus::failure - Functional failed.
1314 bool CMICmdCmdDataWriteMemoryBytes::Execute() {
1315 // Do nothing - not reproduceable (yet) in Eclipse
1316 // CMICMDBASE_GETOPTION( pArgOffset, OptionShort, m_constStrArgOffset );
1317 // CMICMDBASE_GETOPTION( pArgAddr, String, m_constStrArgAddr );
1318 // CMICMDBASE_GETOPTION( pArgNumber, String, m_constStrArgNumber );
1319 // CMICMDBASE_GETOPTION( pArgContents, String, m_constStrArgContents );
1321 // Numbers extracts as string types as they could be hex numbers
1322 // '&' is not recognised and so has to be removed
1324 return MIstatus::success;
1328 // Details: The invoker requires this function. The command prepares a MI Record
1330 // for the work carried out in the Execute().
1331 // Type: Overridden.
1333 // Return: MIstatus::success - Functional succeeded.
1334 // MIstatus::failure - Functional failed.
1337 bool CMICmdCmdDataWriteMemoryBytes::Acknowledge() {
1338 const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED));
1339 const CMICmnMIValueResult miValueResult("msg", miValueConst);
1340 const CMICmnMIResultRecord miRecordResult(
1341 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error,
1343 m_miResultRecord = miRecordResult;
1345 return MIstatus::success;
1349 // Details: Required by the CMICmdFactory when registering *this command. The
1351 // calls this function to create an instance of *this command.
1352 // Type: Static method.
1354 // Return: CMICmdBase * - Pointer to a new command.
1357 CMICmdBase *CMICmdCmdDataWriteMemoryBytes::CreateSelf() {
1358 return new CMICmdCmdDataWriteMemoryBytes();
1363 // Details: CMICmdCmdDataWriteMemory constructor.
1369 CMICmdCmdDataWriteMemory::CMICmdCmdDataWriteMemory()
1370 : m_constStrArgOffset("o"), m_constStrArgAddr("address"),
1371 m_constStrArgD("d"), m_constStrArgNumber("a number"),
1372 m_constStrArgContents("contents"), m_nAddr(0), m_nCount(0),
1373 m_pBufferMemory(nullptr) {
1374 // Command factory matches this name with that received from the stdin stream
1375 m_strMiCmd = "data-write-memory";
1377 // Required by the CMICmdFactory when registering *this command
1378 m_pSelfCreatorFn = &CMICmdCmdDataWriteMemory::CreateSelf;
1382 // Details: CMICmdCmdDataWriteMemory destructor.
1383 // Type: Overrideable.
1388 CMICmdCmdDataWriteMemory::~CMICmdCmdDataWriteMemory() {
1389 if (m_pBufferMemory != nullptr) {
1390 delete[] m_pBufferMemory;
1391 m_pBufferMemory = nullptr;
1396 // Details: The invoker requires this function. The parses the command line
1398 // arguments to extract values for each of those arguments.
1399 // Type: Overridden.
1401 // Return: MIstatus::success - Functional succeeded.
1402 // MIstatus::failure - Functional failed.
1405 bool CMICmdCmdDataWriteMemory::ParseArgs() {
1407 new CMICmdArgValOptionShort(m_constStrArgOffset, false, true,
1408 CMICmdArgValListBase::eArgValType_Number, 1));
1409 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgAddr, true, true));
1410 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgD, true, true));
1411 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumber, true, true));
1412 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgContents, true, true));
1413 return ParseValidateCmdOptions();
1417 // Details: The invoker requires this function. The command does work in this
1419 // The command is likely to communicate with the LLDB SBDebugger in
1421 // Type: Overridden.
1423 // Return: MIstatus::success - Functional succeeded.
1424 // MIstatus::failure - Functional failed.
1427 bool CMICmdCmdDataWriteMemory::Execute() {
1428 CMICMDBASE_GETOPTION(pArgOffset, OptionShort, m_constStrArgOffset);
1429 CMICMDBASE_GETOPTION(pArgAddr, Number, m_constStrArgAddr);
1430 CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNumber);
1431 CMICMDBASE_GETOPTION(pArgContents, Number, m_constStrArgContents);
1433 MIuint nAddrOffset = 0;
1434 if (pArgOffset->GetFound() &&
1435 !pArgOffset->GetExpectedOption<CMICmdArgValNumber, MIuint>(nAddrOffset)) {
1436 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_INVALID),
1437 m_cmdData.strMiCmd.c_str(),
1438 m_constStrArgAddr.c_str()));
1439 return MIstatus::failure;
1441 m_nAddr = pArgAddr->GetValue();
1442 m_nCount = pArgNumber->GetValue();
1443 const MIuint64 nValue = pArgContents->GetValue();
1445 m_pBufferMemory = new unsigned char[m_nCount];
1446 if (m_pBufferMemory == nullptr) {
1447 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_MEMORY_ALLOC_FAILURE),
1448 m_cmdData.strMiCmd.c_str(), m_nCount));
1449 return MIstatus::failure;
1451 *m_pBufferMemory = static_cast<char>(nValue);
1453 CMICmnLLDBDebugSessionInfo &rSessionInfo(
1454 CMICmnLLDBDebugSessionInfo::Instance());
1455 lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
1456 lldb::SBError error;
1457 lldb::addr_t addr = static_cast<lldb::addr_t>(m_nAddr + nAddrOffset);
1458 const size_t nBytesWritten = sbProcess.WriteMemory(
1459 addr, (const void *)m_pBufferMemory, (size_t)m_nCount, error);
1460 if (nBytesWritten != static_cast<size_t>(m_nCount)) {
1462 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_NOT_WRITE_WHOLEBLK),
1463 m_cmdData.strMiCmd.c_str(), m_nCount, addr));
1464 return MIstatus::failure;
1468 const bool bOk = error.GetDescription(err);
1470 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_WRITE_MEM_BYTES),
1471 m_cmdData.strMiCmd.c_str(), m_nCount, addr,
1473 return MIstatus::failure;
1476 return MIstatus::success;
1480 // Details: The invoker requires this function. The command prepares a MI Record
1482 // for the work carried out in the Execute().
1483 // Type: Overridden.
1485 // Return: MIstatus::success - Functional succeeded.
1486 // MIstatus::failure - Functional failed.
1489 bool CMICmdCmdDataWriteMemory::Acknowledge() {
1490 const CMICmnMIResultRecord miRecordResult(
1491 m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done);
1492 m_miResultRecord = miRecordResult;
1494 return MIstatus::success;
1498 // Details: Required by the CMICmdFactory when registering *this command. The
1500 // calls this function to create an instance of *this command.
1501 // Type: Static method.
1503 // Return: CMICmdBase * - Pointer to a new command.
1506 CMICmdBase *CMICmdCmdDataWriteMemory::CreateSelf() {
1507 return new CMICmdCmdDataWriteMemory();
1512 // Details: CMICmdCmdDataInfoLine constructor.
1518 CMICmdCmdDataInfoLine::CMICmdCmdDataInfoLine()
1519 : m_constStrArgLocation("location"),
1520 m_resultRecord(m_cmdData.strMiCmdToken,
1521 CMICmnMIResultRecord::eResultClass_Done) {
1522 // Command factory matches this name with that received from the stdin stream
1523 m_strMiCmd = "data-info-line";
1525 // Required by the CMICmdFactory when registering *this command
1526 m_pSelfCreatorFn = &CMICmdCmdDataInfoLine::CreateSelf;
1530 // Details: CMICmdCmdDataInfoLine destructor.
1531 // Type: Overrideable.
1536 CMICmdCmdDataInfoLine::~CMICmdCmdDataInfoLine() = default;
1539 // Details: The invoker requires this function. The parses the command line
1541 // arguments to extract values for each of those arguments.
1542 // Type: Overridden.
1544 // Return: MIstatus::success - Functional succeeded.
1545 // MIstatus::failure - Functional failed.
1548 bool CMICmdCmdDataInfoLine::ParseArgs() {
1549 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgLocation, true, true));
1550 return ParseValidateCmdOptions();
1554 // Details: The invoker requires this function. The command does work in this
1556 // The command is likely to communicate with the LLDB SBDebugger in
1558 // Type: Overridden.
1560 // Return: MIstatus::success - Functional succeeded.
1561 // MIstatus::failure - Functional failed.
1564 bool CMICmdCmdDataInfoLine::Execute() {
1565 CMICMDBASE_GETOPTION(pArgLocation, String, m_constStrArgLocation);
1567 lldb::SBLineEntry line;
1568 bool found_line = false;
1569 const CMIUtilString &strLocation(pArgLocation->GetValue());
1570 lldb::SBTarget target = CMICmnLLDBDebugSessionInfo::Instance().GetTarget();
1572 if (strLocation.at(0) == '*') {
1575 // ^^^^^^^^^ -- address
1576 lldb::addr_t address = 0x0;
1577 if (llvm::StringRef(strLocation.substr(1)).getAsInteger(0, address)) {
1578 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SOME_ERROR),
1579 m_cmdData.strMiCmd.c_str(),
1580 "Failed to parse address."));
1581 return MIstatus::failure;
1583 line = target.ResolveFileAddress(address).GetLineEntry();
1584 // Check that found line is valid.
1588 const size_t nLineStartPos = strLocation.rfind(':');
1589 if ((nLineStartPos == std::string::npos) || (nLineStartPos == 0) ||
1590 (nLineStartPos == strLocation.length() - 1)) {
1591 SetError(CMIUtilString::Format(
1592 MIRSRC(IDS_CMD_ERR_INVALID_LOCATION_FORMAT),
1593 m_cmdData.strMiCmd.c_str(), strLocation.c_str()));
1594 return MIstatus::failure;
1598 // ^^^^^^^^^ -- file
1600 const CMIUtilString &strFile(strLocation.substr(0, nLineStartPos));
1601 uint32_t numLine = 0;
1602 llvm::StringRef(strLocation.substr(nLineStartPos + 1))
1603 .getAsInteger(0, numLine);
1604 lldb::SBSymbolContextList sc_cu_list =
1605 target.FindCompileUnits(lldb::SBFileSpec(strFile.c_str(), false));
1606 for (uint32_t i = 0, e = sc_cu_list.GetSize(); i < e; ++i) {
1607 const lldb::SBCompileUnit &cu =
1608 sc_cu_list.GetContextAtIndex(i).GetCompileUnit();
1609 // Break if we have already found requested line.
1612 for (uint32_t j = 0, e = cu.GetNumLineEntries(); j < e; ++j) {
1613 const lldb::SBLineEntry &curLine = cu.GetLineEntryAtIndex(j);
1614 if (curLine.GetLine() == numLine) {
1623 SetError(CMIUtilString::Format(
1624 MIRSRC(IDS_CMD_ERR_SOME_ERROR), m_cmdData.strMiCmd.c_str(),
1625 "The LineEntry is absent or has an unknown format."));
1626 return MIstatus::failure;
1629 m_resultRecord.Add(CMICmnMIValueResult(
1630 "start", CMICmnMIValueConst(IntToHexAddrStr(
1631 line.GetStartAddress().GetFileAddress()))));
1633 m_resultRecord.Add(CMICmnMIValueResult(
1634 "end", CMICmnMIValueConst(IntToHexAddrStr(
1635 line.GetEndAddress().GetFileAddress()))));
1637 std::unique_ptr<char[]> upPath(new char[PATH_MAX]);
1638 line.GetFileSpec().GetPath(upPath.get(), PATH_MAX);
1639 m_resultRecord.Add(CMICmnMIValueResult(
1640 "file", CMICmnMIValueConst(CMIUtilString(upPath.get()))));
1642 m_resultRecord.Add(CMICmnMIValueResult(
1643 "line", CMICmnMIValueConst(std::to_string(line.GetLine()))));
1644 return MIstatus::success;
1648 // Details: The invoker requires this function. The command prepares a MI Record
1650 // for the work carried out in the Execute().
1651 // Type: Overridden.
1653 // Return: MIstatus::success - Functional succeeded.
1654 // MIstatus::failure - Functional failed.
1657 bool CMICmdCmdDataInfoLine::Acknowledge() {
1658 m_miResultRecord = m_resultRecord;
1659 return MIstatus::success;
1663 // Details: Required by the CMICmdFactory when registering *this command. The
1665 // calls this function to create an instance of *this command.
1666 // Type: Static method.
1668 // Return: CMICmdBase * - Pointer to a new command.
1671 CMICmdBase *CMICmdCmdDataInfoLine::CreateSelf() {
1672 return new CMICmdCmdDataInfoLine();