1//===-- MICmdCmdData.cpp ----------------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10// Overview: 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. 20 21// Third Party Headers: 22#include <inttypes.h> // For PRIx64 23#include "lldb/API/SBCommandInterpreter.h" 24#include "lldb/API/SBThread.h" 25#include "lldb/API/SBInstruction.h" 26#include "lldb/API/SBInstructionList.h" 27#include "lldb/API/SBStream.h" 28 29// In-house headers: 30#include "MICmdCmdData.h" 31#include "MICmnMIResultRecord.h" 32#include "MICmnMIValueConst.h" 33#include "MICmnLLDBDebugger.h" 34#include "MICmnLLDBDebugSessionInfo.h" 35#include "MICmnLLDBProxySBValue.h" 36#include "MICmdArgValNumber.h" 37#include "MICmdArgValString.h" 38#include "MICmdArgValThreadGrp.h" 39#include "MICmdArgValOptionLong.h" 40#include "MICmdArgValOptionShort.h" 41#include "MICmdArgValListOfN.h" 42#include "MICmdArgValConsume.h" 43#include "MICmnLLDBDebugSessionInfoVarObj.h" 44#include "MICmnLLDBUtilSBValue.h" 45#include "MIUtilParse.h" 46 47//++ ------------------------------------------------------------------------------------ 48// Details: CMICmdCmdDataEvaluateExpression constructor. 49// Type: Method. 50// Args: None. 51// Return: None. 52// Throws: None. 53//-- 54CMICmdCmdDataEvaluateExpression::CMICmdCmdDataEvaluateExpression() 55 : m_bExpressionValid(true) 56 , m_bEvaluatedExpression(true) 57 , m_strValue("??") 58 , m_bFoundInvalidChar(false) 59 , m_cExpressionInvalidChar(0x00) 60 , m_constStrArgExpr("expr") 61{ 62 // Command factory matches this name with that received from the stdin stream 63 m_strMiCmd = "data-evaluate-expression"; 64 65 // Required by the CMICmdFactory when registering *this command 66 m_pSelfCreatorFn = &CMICmdCmdDataEvaluateExpression::CreateSelf; 67} 68 69//++ ------------------------------------------------------------------------------------ 70// Details: CMICmdCmdDataEvaluateExpression destructor. 71// Type: Overrideable. 72// Args: None. 73// Return: None. 74// Throws: None. 75//-- 76CMICmdCmdDataEvaluateExpression::~CMICmdCmdDataEvaluateExpression() 77{ 78} 79 80//++ ------------------------------------------------------------------------------------ 81// Details: The invoker requires this function. The parses the command line options 82// arguments to extract values for each of those arguments. 83// Type: Overridden. 84// Args: None. 85// Return: MIstatus::success - Functional succeeded. 86// MIstatus::failure - Functional failed. 87// Throws: None. 88//-- 89bool 90CMICmdCmdDataEvaluateExpression::ParseArgs() 91{ 92 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgExpr, true, true, true, true)); 93 return ParseValidateCmdOptions(); 94} 95 96//++ ------------------------------------------------------------------------------------ 97// Details: The invoker requires this function. The command does work in this function. 98// The command is likely to communicate with the LLDB SBDebugger in here. 99// Type: Overridden. 100// Args: None. 101// Return: MIstatus::success - Functional succeeded. 102// MIstatus::failure - Functional failed. 103// Throws: None. 104//-- 105bool 106CMICmdCmdDataEvaluateExpression::Execute() 107{ 108 CMICMDBASE_GETOPTION(pArgExpr, String, m_constStrArgExpr); 109 110 const CMIUtilString &rExpression(pArgExpr->GetValue()); 111 CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); 112 lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); 113 lldb::SBThread thread = sbProcess.GetSelectedThread(); 114 m_bExpressionValid = (thread.GetNumFrames() > 0); 115 if (!m_bExpressionValid) 116 return MIstatus::success; 117 118 lldb::SBFrame frame = thread.GetSelectedFrame(); 119 lldb::SBValue value = frame.EvaluateExpression(rExpression.c_str()); 120 if (!value.IsValid() || value.GetError().Fail()) 121 value = frame.FindVariable(rExpression.c_str()); 122 const CMICmnLLDBUtilSBValue utilValue(value, true); 123 if (!utilValue.IsValid() || utilValue.IsValueUnknown()) 124 { 125 m_bEvaluatedExpression = false; 126 return MIstatus::success; 127 } 128 if (!utilValue.HasName()) 129 { 130 if (HaveInvalidCharacterInExpression(rExpression, m_cExpressionInvalidChar)) 131 { 132 m_bFoundInvalidChar = true; 133 return MIstatus::success; 134 } 135 136 m_strValue = rExpression; 137 return MIstatus::success; 138 } 139 if (rExpression.IsQuoted()) 140 { 141 m_strValue = rExpression.Trim('\"'); 142 return MIstatus::success; 143 } 144 m_strValue = utilValue.GetValue(true).Escape().AddSlashes(); 145 return MIstatus::success; 146} 147 148//++ ------------------------------------------------------------------------------------ 149// Details: The invoker requires this function. The command prepares a MI Record Result 150// for the work carried out in the Execute(). 151// Type: Overridden. 152// Args: None. 153// Return: MIstatus::success - Functional succeeded. 154// MIstatus::failure - Functional failed. 155// Throws: None. 156//-- 157bool 158CMICmdCmdDataEvaluateExpression::Acknowledge() 159{ 160 if (m_bExpressionValid) 161 { 162 if (m_bEvaluatedExpression) 163 { 164 if (m_bFoundInvalidChar) 165 { 166 const CMICmnMIValueConst miValueConst( 167 CMIUtilString::Format("Invalid character '%c' in expression", m_cExpressionInvalidChar)); 168 const CMICmnMIValueResult miValueResult("msg", miValueConst); 169 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); 170 m_miResultRecord = miRecordResult; 171 return MIstatus::success; 172 } 173 174 const CMICmnMIValueConst miValueConst(m_strValue); 175 const CMICmnMIValueResult miValueResult("value", miValueConst); 176 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); 177 m_miResultRecord = miRecordResult; 178 return MIstatus::success; 179 } 180 181 const CMICmnMIValueConst miValueConst("Could not evaluate expression"); 182 const CMICmnMIValueResult miValueResult("msg", miValueConst); 183 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); 184 m_miResultRecord = miRecordResult; 185 return MIstatus::success; 186 } 187 188 const CMICmnMIValueConst miValueConst("Invalid expression"); 189 const CMICmnMIValueResult miValueResult("msg", miValueConst); 190 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); 191 m_miResultRecord = miRecordResult; 192 193 return MIstatus::success; 194} 195 196//++ ------------------------------------------------------------------------------------ 197// Details: Required by the CMICmdFactory when registering *this command. The factory 198// calls this function to create an instance of *this command. 199// Type: Static method. 200// Args: None. 201// Return: CMICmdBase * - Pointer to a new command. 202// Throws: None. 203//-- 204CMICmdBase * 205CMICmdCmdDataEvaluateExpression::CreateSelf() 206{ 207 return new CMICmdCmdDataEvaluateExpression(); 208} 209 210//++ ------------------------------------------------------------------------------------ 211// Details: Examine the expression string to see if it contains invalid characters. 212// Type: Method. 213// Args: vrExpr - (R) Expression string given to *this command. 214// vrwInvalidChar - (W) True = Invalid character found, false = nothing found. 215// Return: bool - True = Invalid character found, false = nothing found. 216// Throws: None. 217//-- 218bool 219CMICmdCmdDataEvaluateExpression::HaveInvalidCharacterInExpression(const CMIUtilString &vrExpr, char &vrwInvalidChar) 220{ 221 static const std::string strInvalidCharacters(";#\\"); 222 const size_t nInvalidCharacterOffset = vrExpr.find_first_of(strInvalidCharacters); 223 const bool bFoundInvalidCharInExpression = (nInvalidCharacterOffset != CMIUtilString::npos); 224 vrwInvalidChar = bFoundInvalidCharInExpression ? vrExpr[nInvalidCharacterOffset] : 0x00; 225 return bFoundInvalidCharInExpression; 226} 227 228//--------------------------------------------------------------------------------------- 229//--------------------------------------------------------------------------------------- 230//--------------------------------------------------------------------------------------- 231 232//++ ------------------------------------------------------------------------------------ 233// Details: CMICmdCmdDataDisassemble constructor. 234// Type: Method. 235// Args: None. 236// Return: None. 237// Throws: None. 238//-- 239CMICmdCmdDataDisassemble::CMICmdCmdDataDisassemble() 240 : m_constStrArgAddrStart("s") 241 , m_constStrArgAddrEnd("e") 242 , m_constStrArgMode("mode") 243 , m_miValueList(true) 244{ 245 // Command factory matches this name with that received from the stdin stream 246 m_strMiCmd = "data-disassemble"; 247 248 // Required by the CMICmdFactory when registering *this command 249 m_pSelfCreatorFn = &CMICmdCmdDataDisassemble::CreateSelf; 250} 251 252//++ ------------------------------------------------------------------------------------ 253// Details: CMICmdCmdDataDisassemble destructor. 254// Type: Overrideable. 255// Args: None. 256// Return: None. 257// Throws: None. 258//-- 259CMICmdCmdDataDisassemble::~CMICmdCmdDataDisassemble() 260{ 261} 262 263//++ ------------------------------------------------------------------------------------ 264// Details: The invoker requires this function. The parses the command line options 265// arguments to extract values for each of those arguments. 266// Type: Overridden. 267// Args: None. 268// Return: MIstatus::success - Functional succeeded. 269// MIstatus::failure - Functional failed. 270// Throws: None. 271//-- 272bool 273CMICmdCmdDataDisassemble::ParseArgs() 274{ 275 m_setCmdArgs.Add( 276 new CMICmdArgValOptionShort(m_constStrArgAddrStart, true, true, CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1)); 277 m_setCmdArgs.Add( 278 new CMICmdArgValOptionShort(m_constStrArgAddrEnd, true, true, CMICmdArgValListBase::eArgValType_StringQuotedNumber, 1)); 279 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgMode, true, true)); 280 return ParseValidateCmdOptions(); 281} 282 283//++ ------------------------------------------------------------------------------------ 284// Details: The invoker requires this function. The command does work in this function. 285// The command is likely to communicate with the LLDB SBDebugger in here. 286// Type: Overridden. 287// Args: None. 288// Return: MIstatus::success - Functional succeeded. 289// MIstatus::failure - Functional failed. 290// Throws: None. 291//-- 292bool 293CMICmdCmdDataDisassemble::Execute() 294{ 295 CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); 296 CMICMDBASE_GETOPTION(pArgAddrStart, OptionShort, m_constStrArgAddrStart); 297 CMICMDBASE_GETOPTION(pArgAddrEnd, OptionShort, m_constStrArgAddrEnd); 298 CMICMDBASE_GETOPTION(pArgMode, Number, m_constStrArgMode); 299 300 // Retrieve the --thread option's thread ID (only 1) 301 MIuint64 nThreadId = UINT64_MAX; 302 if (pArgThread->GetFound() && !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) 303 { 304 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); 305 return MIstatus::failure; 306 } 307 CMIUtilString strAddrStart; 308 if (!pArgAddrStart->GetExpectedOption<CMICmdArgValString, CMIUtilString>(strAddrStart)) 309 { 310 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_START_INVALID), m_cmdData.strMiCmd.c_str(), 311 m_constStrArgAddrStart.c_str())); 312 return MIstatus::failure; 313 } 314 MIint64 nAddrStart = 0; 315 if (!strAddrStart.ExtractNumber(nAddrStart)) 316 { 317 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_START_INVALID), m_cmdData.strMiCmd.c_str(), 318 m_constStrArgAddrStart.c_str())); 319 return MIstatus::failure; 320 } 321 322 CMIUtilString strAddrEnd; 323 if (!pArgAddrEnd->GetExpectedOption<CMICmdArgValString, CMIUtilString>(strAddrEnd)) 324 { 325 SetError( 326 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_END_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgAddrEnd.c_str())); 327 return MIstatus::failure; 328 } 329 MIint64 nAddrEnd = 0; 330 if (!strAddrEnd.ExtractNumber(nAddrEnd)) 331 { 332 SetError( 333 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_DISASM_ADDR_END_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgAddrEnd.c_str())); 334 return MIstatus::failure; 335 } 336 const MIuint nDisasmMode = pArgMode->GetValue(); 337 338 CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); 339 lldb::SBTarget sbTarget = rSessionInfo.GetTarget(); 340 lldb::addr_t lldbStartAddr = static_cast<lldb::addr_t>(nAddrStart); 341 lldb::SBInstructionList instructions = sbTarget.ReadInstructions(lldb::SBAddress(lldbStartAddr, sbTarget), nAddrEnd - nAddrStart); 342 const MIuint nInstructions = instructions.GetSize(); 343 // Calculate the offset of first instruction so that we can generate offset starting at 0 344 lldb::addr_t start_offset = 0; 345 if(nInstructions > 0) 346 start_offset = instructions.GetInstructionAtIndex(0).GetAddress().GetOffset(); 347 348 for (size_t i = 0; i < nInstructions; i++) 349 { 350 const char *pUnknown = "??"; 351 lldb::SBInstruction instrt = instructions.GetInstructionAtIndex(i); 352 const char *pStrMnemonic = instrt.GetMnemonic(sbTarget); 353 pStrMnemonic = (pStrMnemonic != nullptr) ? pStrMnemonic : pUnknown; 354 const char *pStrComment = instrt.GetComment(sbTarget); 355 CMIUtilString strComment; 356 if (pStrComment != nullptr && *pStrComment != '\0') 357 strComment = CMIUtilString::Format("; %s", pStrComment); 358 lldb::SBAddress address = instrt.GetAddress(); 359 lldb::addr_t addr = address.GetLoadAddress(sbTarget); 360 const char *pFnName = address.GetFunction().GetName(); 361 pFnName = (pFnName != nullptr) ? pFnName : pUnknown; 362 lldb::addr_t addrOffSet = address.GetOffset() - start_offset; 363 const char *pStrOperands = instrt.GetOperands(sbTarget); 364 pStrOperands = (pStrOperands != nullptr) ? pStrOperands : pUnknown; 365 const size_t instrtSize = instrt.GetByteSize(); 366 367 // MI "{address=\"0x%016" PRIx64 "\",func-name=\"%s\",offset=\"%lld\",inst=\"%s %s\"}" 368 const CMICmnMIValueConst miValueConst(CMIUtilString::Format("0x%016" PRIx64, addr)); 369 const CMICmnMIValueResult miValueResult("address", miValueConst); 370 CMICmnMIValueTuple miValueTuple(miValueResult); 371 const CMICmnMIValueConst miValueConst2(pFnName); 372 const CMICmnMIValueResult miValueResult2("func-name", miValueConst2); 373 miValueTuple.Add(miValueResult2); 374 const CMICmnMIValueConst miValueConst3(CMIUtilString::Format("%lld", addrOffSet)); 375 const CMICmnMIValueResult miValueResult3("offset", miValueConst3); 376 miValueTuple.Add(miValueResult3); 377 const CMICmnMIValueConst miValueConst4(CMIUtilString::Format("%d", instrtSize)); 378 const CMICmnMIValueResult miValueResult4("size", miValueConst4); 379 miValueTuple.Add(miValueResult4); 380 const CMICmnMIValueConst miValueConst5(CMIUtilString::Format("%s %s%s", pStrMnemonic, pStrOperands, strComment.Escape(true).c_str())); 381 const CMICmnMIValueResult miValueResult5("inst", miValueConst5); 382 miValueTuple.Add(miValueResult5); 383 384 if (nDisasmMode == 1) 385 { 386 lldb::SBLineEntry lineEntry = address.GetLineEntry(); 387 const MIuint nLine = lineEntry.GetLine(); 388 const char *pFileName = lineEntry.GetFileSpec().GetFilename(); 389 pFileName = (pFileName != nullptr) ? pFileName : pUnknown; 390 391 // MI "src_and_asm_line={line=\"%u\",file=\"%s\",line_asm_insn=[ ]}" 392 const CMICmnMIValueConst miValueConst(CMIUtilString::Format("0x%u", nLine)); 393 const CMICmnMIValueResult miValueResult("line", miValueConst); 394 CMICmnMIValueTuple miValueTuple2(miValueResult); 395 const CMICmnMIValueConst miValueConst2(pFileName); 396 const CMICmnMIValueResult miValueResult2("file", miValueConst2); 397 miValueTuple2.Add(miValueResult2); 398 const CMICmnMIValueList miValueList(miValueTuple); 399 const CMICmnMIValueResult miValueResult3("line_asm_insn", miValueList); 400 miValueTuple2.Add(miValueResult3); 401 const CMICmnMIValueResult miValueResult4("src_and_asm_line", miValueTuple2); 402 m_miValueList.Add(miValueResult4); 403 } 404 else 405 { 406 m_miValueList.Add(miValueTuple); 407 } 408 } 409 410 return MIstatus::success; 411} 412 413//++ ------------------------------------------------------------------------------------ 414// Details: The invoker requires this function. The command prepares a MI Record Result 415// for the work carried out in the Execute(). 416// Type: Overridden. 417// Args: None. 418// Return: MIstatus::success - Functional succeeded. 419// MIstatus::failure - Functional failed. 420// Throws: None. 421//-- 422bool 423CMICmdCmdDataDisassemble::Acknowledge() 424{ 425 const CMICmnMIValueResult miValueResult("asm_insns", m_miValueList); 426 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); 427 m_miResultRecord = miRecordResult; 428 429 return MIstatus::success; 430} 431 432//++ ------------------------------------------------------------------------------------ 433// Details: Required by the CMICmdFactory when registering *this command. The factory 434// calls this function to create an instance of *this command. 435// Type: Static method. 436// Args: None. 437// Return: CMICmdBase * - Pointer to a new command. 438// Throws: None. 439//-- 440CMICmdBase * 441CMICmdCmdDataDisassemble::CreateSelf() 442{ 443 return new CMICmdCmdDataDisassemble(); 444} 445 446//--------------------------------------------------------------------------------------- 447//--------------------------------------------------------------------------------------- 448//--------------------------------------------------------------------------------------- 449 450//++ ------------------------------------------------------------------------------------ 451// Details: CMICmdCmdDataReadMemoryBytes constructor. 452// Type: Method. 453// Args: None. 454// Return: None. 455// Throws: None. 456//-- 457CMICmdCmdDataReadMemoryBytes::CMICmdCmdDataReadMemoryBytes() 458 : m_constStrArgByteOffset("o") 459 , m_constStrArgAddrExpr("address") 460 , m_constStrArgNumBytes("count") 461 , m_pBufferMemory(nullptr) 462 , m_nAddrStart(0) 463 , m_nAddrNumBytesToRead(0) 464{ 465 // Command factory matches this name with that received from the stdin stream 466 m_strMiCmd = "data-read-memory-bytes"; 467 468 // Required by the CMICmdFactory when registering *this command 469 m_pSelfCreatorFn = &CMICmdCmdDataReadMemoryBytes::CreateSelf; 470} 471 472//++ ------------------------------------------------------------------------------------ 473// Details: CMICmdCmdDataReadMemoryBytes destructor. 474// Type: Overrideable. 475// Args: None. 476// Return: None. 477// Throws: None. 478//-- 479CMICmdCmdDataReadMemoryBytes::~CMICmdCmdDataReadMemoryBytes() 480{ 481 if (m_pBufferMemory != nullptr) 482 { 483 delete[] m_pBufferMemory; 484 m_pBufferMemory = nullptr; 485 } 486} 487 488//++ ------------------------------------------------------------------------------------ 489// Details: The invoker requires this function. The parses the command line options 490// arguments to extract values for each of those arguments. 491// Type: Overridden. 492// Args: None. 493// Return: MIstatus::success - Functional succeeded. 494// MIstatus::failure - Functional failed. 495// Throws: None. 496//-- 497bool 498CMICmdCmdDataReadMemoryBytes::ParseArgs() 499{ 500 m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgByteOffset, false, true, CMICmdArgValListBase::eArgValType_Number, 1)); 501 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgAddrExpr, true, true, true, true)); 502 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumBytes, true, true)); 503 return ParseValidateCmdOptions(); 504} 505 506//++ ------------------------------------------------------------------------------------ 507// Details: The invoker requires this function. The command does work in this function. 508// The command is likely to communicate with the LLDB SBDebugger in here. 509// Type: Overridden. 510// Args: None. 511// Return: MIstatus::success - Function succeeded. 512// MIstatus::failure - Function failed. 513// Throws: None. 514//-- 515bool 516CMICmdCmdDataReadMemoryBytes::Execute() 517{ 518 CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); 519 CMICMDBASE_GETOPTION(pArgFrame, OptionLong, m_constStrArgFrame); 520 CMICMDBASE_GETOPTION(pArgAddrOffset, OptionShort, m_constStrArgByteOffset); 521 CMICMDBASE_GETOPTION(pArgAddrExpr, String, m_constStrArgAddrExpr); 522 CMICMDBASE_GETOPTION(pArgNumBytes, Number, m_constStrArgNumBytes); 523 524 // get the --thread option value 525 MIuint64 nThreadId = UINT64_MAX; 526 if (pArgThread->GetFound() && !pArgThread->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nThreadId)) 527 { 528 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), 529 m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); 530 return MIstatus::failure; 531 } 532 533 // get the --frame option value 534 MIuint64 nFrame = UINT64_MAX; 535 if (pArgFrame->GetFound() && !pArgFrame->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nFrame)) 536 { 537 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), 538 m_cmdData.strMiCmd.c_str(), m_constStrArgFrame.c_str())); 539 return MIstatus::failure; 540 } 541 542 // get the -o option value 543 MIuint64 nAddrOffset = 0; 544 if (pArgAddrOffset->GetFound() && !pArgAddrOffset->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nAddrOffset)) 545 { 546 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), 547 m_cmdData.strMiCmd.c_str(), m_constStrArgByteOffset.c_str())); 548 return MIstatus::failure; 549 } 550 551 CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); 552 lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); 553 if (!sbProcess.IsValid()) 554 { 555 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str())); 556 return MIstatus::failure; 557 } 558 559 lldb::SBThread thread = (nThreadId != UINT64_MAX) ? 560 sbProcess.GetThreadByIndexID(nThreadId) : sbProcess.GetSelectedThread(); 561 if (!thread.IsValid()) 562 { 563 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), m_cmdData.strMiCmd.c_str())); 564 return MIstatus::failure; 565 } 566 567 lldb::SBFrame frame = (nFrame != UINT64_MAX) ? 568 thread.GetFrameAtIndex(nFrame) : thread.GetSelectedFrame(); 569 if (!frame.IsValid()) 570 { 571 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FRAME_INVALID), m_cmdData.strMiCmd.c_str())); 572 return MIstatus::failure; 573 } 574 575 const CMIUtilString &rAddrExpr = pArgAddrExpr->GetValue(); 576 lldb::SBValue addrExprValue = frame.EvaluateExpression(rAddrExpr.c_str()); 577 lldb::SBError error = addrExprValue.GetError(); 578 if (error.Fail()) 579 { 580 SetError(error.GetCString()); 581 return MIstatus::failure; 582 } 583 else if (!addrExprValue.IsValid()) 584 { 585 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_EXPR_INVALID), rAddrExpr.c_str())); 586 return MIstatus::failure; 587 } 588 589 MIuint64 nAddrStart = 0; 590 if (!CMICmnLLDBProxySBValue::GetValueAsUnsigned(addrExprValue, nAddrStart)) 591 { 592 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_EXPR_INVALID), rAddrExpr.c_str())); 593 return MIstatus::failure; 594 } 595 596 nAddrStart += nAddrOffset; 597 const MIuint64 nAddrNumBytes = pArgNumBytes->GetValue(); 598 599 m_pBufferMemory = new unsigned char[nAddrNumBytes]; 600 if (m_pBufferMemory == nullptr) 601 { 602 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_MEMORY_ALLOC_FAILURE), m_cmdData.strMiCmd.c_str(), nAddrNumBytes)); 603 return MIstatus::failure; 604 } 605 606 const MIuint64 nReadBytes = sbProcess.ReadMemory(static_cast<lldb::addr_t>(nAddrStart), (void *)m_pBufferMemory, nAddrNumBytes, error); 607 if (nReadBytes != nAddrNumBytes) 608 { 609 SetError( 610 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_NOT_READ_WHOLE_BLK), m_cmdData.strMiCmd.c_str(), nAddrNumBytes, nAddrStart)); 611 return MIstatus::failure; 612 } 613 if (error.Fail()) 614 { 615 lldb::SBStream err; 616 const bool bOk = error.GetDescription(err); 617 MIunused(bOk); 618 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_READ_MEM_BYTES), m_cmdData.strMiCmd.c_str(), nAddrNumBytes, nAddrStart, 619 err.GetData())); 620 return MIstatus::failure; 621 } 622 623 m_nAddrStart = nAddrStart; 624 m_nAddrNumBytesToRead = nAddrNumBytes; 625 626 return MIstatus::success; 627} 628 629//++ ------------------------------------------------------------------------------------ 630// Details: The invoker requires this function. The command prepares a MI Record Result 631// for the work carried out in the Execute(). 632// Type: Overridden. 633// Args: None. 634// Return: MIstatus::success - Functional succeeded. 635// MIstatus::failure - Functional failed. 636// Throws: None. 637//-- 638bool 639CMICmdCmdDataReadMemoryBytes::Acknowledge() 640{ 641 // MI: memory=[{begin=\"0x%016" PRIx64 "\",offset=\"0x%016" PRIx64" \",end=\"0x%016" PRIx64 "\",contents=\" \" }]" 642 const CMICmnMIValueConst miValueConst(CMIUtilString::Format("0x%016" PRIx64, m_nAddrStart)); 643 const CMICmnMIValueResult miValueResult("begin", miValueConst); 644 CMICmnMIValueTuple miValueTuple(miValueResult); 645 const MIuint64 nAddrOffset = 0; 646 const CMICmnMIValueConst miValueConst2(CMIUtilString::Format("0x%016" PRIx64, nAddrOffset)); 647 const CMICmnMIValueResult miValueResult2("offset", miValueConst2); 648 miValueTuple.Add(miValueResult2); 649 const CMICmnMIValueConst miValueConst3(CMIUtilString::Format("0x%016" PRIx64, m_nAddrStart + m_nAddrNumBytesToRead)); 650 const CMICmnMIValueResult miValueResult3("end", miValueConst3); 651 miValueTuple.Add(miValueResult3); 652 653 // MI: contents=\" \" 654 CMIUtilString strContent; 655 strContent.reserve((m_nAddrNumBytesToRead << 1) + 1); 656 for (MIuint64 i = 0; i < m_nAddrNumBytesToRead; i++) 657 { 658 strContent += CMIUtilString::Format("%02hhx", m_pBufferMemory[i]); 659 } 660 const CMICmnMIValueConst miValueConst4(strContent); 661 const CMICmnMIValueResult miValueResult4("contents", miValueConst4); 662 miValueTuple.Add(miValueResult4); 663 const CMICmnMIValueList miValueList(miValueTuple); 664 const CMICmnMIValueResult miValueResult5("memory", miValueList); 665 666 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult5); 667 m_miResultRecord = miRecordResult; 668 669 return MIstatus::success; 670} 671 672//++ ------------------------------------------------------------------------------------ 673// Details: Required by the CMICmdFactory when registering *this command. The factory 674// calls this function to create an instance of *this command. 675// Type: Static method. 676// Args: None. 677// Return: CMICmdBase * - Pointer to a new command. 678// Throws: None. 679//-- 680CMICmdBase * 681CMICmdCmdDataReadMemoryBytes::CreateSelf() 682{ 683 return new CMICmdCmdDataReadMemoryBytes(); 684} 685 686//--------------------------------------------------------------------------------------- 687//--------------------------------------------------------------------------------------- 688//--------------------------------------------------------------------------------------- 689 690//++ ------------------------------------------------------------------------------------ 691// Details: CMICmdCmdDataReadMemory constructor. 692// Type: Method. 693// Args: None. 694// Return: None. 695// Throws: None. 696//-- 697CMICmdCmdDataReadMemory::CMICmdCmdDataReadMemory() 698{ 699 // Command factory matches this name with that received from the stdin stream 700 m_strMiCmd = "data-read-memory"; 701 702 // Required by the CMICmdFactory when registering *this command 703 m_pSelfCreatorFn = &CMICmdCmdDataReadMemory::CreateSelf; 704} 705 706//++ ------------------------------------------------------------------------------------ 707// Details: CMICmdCmdDataReadMemory destructor. 708// Type: Overrideable. 709// Args: None. 710// Return: None. 711// Throws: None. 712//-- 713CMICmdCmdDataReadMemory::~CMICmdCmdDataReadMemory() 714{ 715} 716 717//++ ------------------------------------------------------------------------------------ 718// Details: The invoker requires this function. The command does work in this function. 719// The command is likely to communicate with the LLDB SBDebugger in here. 720// Type: Overridden. 721// Args: None. 722// Return: MIstatus::success - Functional succeeded. 723// MIstatus::failure - Functional failed. 724// Throws: None. 725//-- 726bool 727CMICmdCmdDataReadMemory::Execute() 728{ 729 // Do nothing - command deprecated use "data-read-memory-bytes" command 730 return MIstatus::success; 731} 732 733//++ ------------------------------------------------------------------------------------ 734// Details: The invoker requires this function. The command prepares a MI Record Result 735// for the work carried out in the Execute(). 736// Type: Overridden. 737// Args: None. 738// Return: MIstatus::success - Functional succeeded. 739// MIstatus::failure - Functional failed. 740// Throws: None. 741//-- 742bool 743CMICmdCmdDataReadMemory::Acknowledge() 744{ 745 // Command CMICmdCmdSupportListFeatures sends "data-read-memory-bytes" which causes this command not to be called 746 const CMICmnMIValueConst miValueConst(MIRSRC(IDS_CMD_ERR_NOT_IMPLEMENTED_DEPRECATED)); 747 const CMICmnMIValueResult miValueResult("msg", miValueConst); 748 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); 749 m_miResultRecord = miRecordResult; 750 751 return MIstatus::success; 752} 753 754//++ ------------------------------------------------------------------------------------ 755// Details: Required by the CMICmdFactory when registering *this command. The factory 756// calls this function to create an instance of *this command. 757// Type: Static method. 758// Args: None. 759// Return: CMICmdBase * - Pointer to a new command. 760// Throws: None. 761//-- 762CMICmdBase * 763CMICmdCmdDataReadMemory::CreateSelf() 764{ 765 return new CMICmdCmdDataReadMemory(); 766} 767 768//--------------------------------------------------------------------------------------- 769//--------------------------------------------------------------------------------------- 770//--------------------------------------------------------------------------------------- 771 772//++ ------------------------------------------------------------------------------------ 773// Details: CMICmdCmdDataListRegisterNames constructor. 774// Type: Method. 775// Args: None. 776// Return: None. 777// Throws: None. 778//-- 779CMICmdCmdDataListRegisterNames::CMICmdCmdDataListRegisterNames() 780 : m_constStrArgRegNo("regno") 781 , m_miValueList(true) 782{ 783 // Command factory matches this name with that received from the stdin stream 784 m_strMiCmd = "data-list-register-names"; 785 786 // Required by the CMICmdFactory when registering *this command 787 m_pSelfCreatorFn = &CMICmdCmdDataListRegisterNames::CreateSelf; 788} 789 790//++ ------------------------------------------------------------------------------------ 791// Details: CMICmdCmdDataReadMemoryBytes destructor. 792// Type: Overrideable. 793// Args: None. 794// Return: None. 795// Throws: None. 796//-- 797CMICmdCmdDataListRegisterNames::~CMICmdCmdDataListRegisterNames() 798{ 799} 800 801//++ ------------------------------------------------------------------------------------ 802// Details: The invoker requires this function. The parses the command line options 803// arguments to extract values for each of those arguments. 804// Type: Overridden. 805// Args: None. 806// Return: MIstatus::success - Functional succeeded. 807// MIstatus::failure - Functional failed. 808// Throws: None. 809//-- 810bool 811CMICmdCmdDataListRegisterNames::ParseArgs() 812{ 813 m_setCmdArgs.Add(new CMICmdArgValListOfN(m_constStrArgRegNo, false, false, CMICmdArgValListBase::eArgValType_Number)); 814 return ParseValidateCmdOptions(); 815} 816 817//++ ------------------------------------------------------------------------------------ 818// Details: The invoker requires this function. The command does work in this function. 819// The command is likely to communicate with the LLDB SBDebugger in here. 820// Type: Overridden. 821// Args: None. 822// Return: MIstatus::success - Functional succeeded. 823// MIstatus::failure - Functional failed. 824// Throws: None. 825//-- 826bool 827CMICmdCmdDataListRegisterNames::Execute() 828{ 829 CMICMDBASE_GETOPTION(pArgRegNo, ListOfN, m_constStrArgRegNo); 830 831 CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); 832 lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); 833 if (!sbProcess.IsValid()) 834 { 835 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str())); 836 return MIstatus::failure; 837 } 838 839 const CMICmdArgValListBase::VecArgObjPtr_t &rVecRegNo(pArgRegNo->GetExpectedOptions()); 840 if (!rVecRegNo.empty()) 841 { 842 // List of required registers 843 CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecRegNo.begin(); 844 while (it != rVecRegNo.end()) 845 { 846 const CMICmdArgValNumber *pRegNo = static_cast<CMICmdArgValNumber *>(*it); 847 const MIuint nRegIndex = pRegNo->GetValue(); 848 lldb::SBValue regValue = GetRegister(nRegIndex); 849 if (regValue.IsValid()) 850 { 851 const CMICmnMIValueConst miValueConst(CMICmnLLDBUtilSBValue(regValue).GetName()); 852 m_miValueList.Add(miValueConst); 853 } 854 855 // Next 856 ++it; 857 } 858 } 859 else 860 { 861 // List of all registers 862 lldb::SBThread thread = sbProcess.GetSelectedThread(); 863 lldb::SBFrame frame = thread.GetSelectedFrame(); 864 lldb::SBValueList registers = frame.GetRegisters(); 865 const MIuint nRegisters = registers.GetSize(); 866 for (MIuint i = 0; i < nRegisters; i++) 867 { 868 lldb::SBValue value = registers.GetValueAtIndex(i); 869 const MIuint nRegChildren = value.GetNumChildren(); 870 for (MIuint j = 0; j < nRegChildren; j++) 871 { 872 lldb::SBValue regValue = value.GetChildAtIndex(j); 873 if (regValue.IsValid()) 874 { 875 const CMICmnMIValueConst miValueConst(CMICmnLLDBUtilSBValue(regValue).GetName()); 876 m_miValueList.Add(miValueConst); 877 } 878 } 879 } 880 } 881 882 return MIstatus::success; 883} 884 885//++ ------------------------------------------------------------------------------------ 886// Details: The invoker requires this function. The command prepares a MI Record Result 887// for the work carried out in the Execute(). 888// Type: Overridden. 889// Args: None. 890// Return: MIstatus::success - Functional succeeded. 891// MIstatus::failure - Functional failed. 892// Throws: None. 893//-- 894bool 895CMICmdCmdDataListRegisterNames::Acknowledge() 896{ 897 const CMICmnMIValueResult miValueResult("register-names", m_miValueList); 898 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); 899 m_miResultRecord = miRecordResult; 900 901 return MIstatus::success; 902} 903 904//++ ------------------------------------------------------------------------------------ 905// Details: Required by the CMICmdFactory when registering *this command. The factory 906// calls this function to create an instance of *this command. 907// Type: Static method. 908// Args: None. 909// Return: CMICmdBase * - Pointer to a new command. 910// Throws: None. 911//-- 912CMICmdBase * 913CMICmdCmdDataListRegisterNames::CreateSelf() 914{ 915 return new CMICmdCmdDataListRegisterNames(); 916} 917 918//++ ------------------------------------------------------------------------------------ 919// Details: Required by the CMICmdFactory when registering *this command. The factory 920// calls this function to create an instance of *this command. 921// Type: Method. 922// Args: None. 923// Return: lldb::SBValue - LLDB SBValue object. 924// Throws: None. 925//-- 926lldb::SBValue 927CMICmdCmdDataListRegisterNames::GetRegister(const MIuint vRegisterIndex) const 928{ 929 lldb::SBThread thread = CMICmnLLDBDebugSessionInfo::Instance().GetProcess().GetSelectedThread(); 930 lldb::SBFrame frame = thread.GetSelectedFrame(); 931 lldb::SBValueList registers = frame.GetRegisters(); 932 const MIuint nRegisters = registers.GetSize(); 933 MIuint nRegisterIndex(vRegisterIndex); 934 for (MIuint i = 0; i < nRegisters; i++) 935 { 936 lldb::SBValue value = registers.GetValueAtIndex(i); 937 const MIuint nRegChildren = value.GetNumChildren(); 938 if (nRegisterIndex >= nRegChildren) 939 { 940 nRegisterIndex -= nRegChildren; 941 continue; 942 } 943 944 lldb::SBValue value2 = value.GetChildAtIndex(nRegisterIndex); 945 if (value2.IsValid()) 946 { 947 return value2; 948 } 949 } 950 951 return lldb::SBValue(); 952} 953 954//--------------------------------------------------------------------------------------- 955//--------------------------------------------------------------------------------------- 956//--------------------------------------------------------------------------------------- 957 958//++ ------------------------------------------------------------------------------------ 959// Details: CMICmdCmdDataListRegisterValues constructor. 960// Type: Method. 961// Args: None. 962// Return: None. 963// Throws: None. 964//-- 965CMICmdCmdDataListRegisterValues::CMICmdCmdDataListRegisterValues() 966 : m_constStrArgSkip("skip-unavailable") 967 , m_constStrArgFormat("fmt") 968 , m_constStrArgRegNo("regno") 969 , m_miValueList(true) 970{ 971 // Command factory matches this name with that received from the stdin stream 972 m_strMiCmd = "data-list-register-values"; 973 974 // Required by the CMICmdFactory when registering *this command 975 m_pSelfCreatorFn = &CMICmdCmdDataListRegisterValues::CreateSelf; 976} 977 978//++ ------------------------------------------------------------------------------------ 979// Details: CMICmdCmdDataListRegisterValues destructor. 980// Type: Overrideable. 981// Args: None. 982// Return: None. 983// Throws: None. 984//-- 985CMICmdCmdDataListRegisterValues::~CMICmdCmdDataListRegisterValues() 986{ 987} 988 989//++ ------------------------------------------------------------------------------------ 990// Details: The invoker requires this function. The parses the command line options 991// arguments to extract values for each of those arguments. 992// Type: Overridden. 993// Args: None. 994// Return: MIstatus::success - Functional succeeded. 995// MIstatus::failure - Functional failed. 996// Throws: None. 997//-- 998bool 999CMICmdCmdDataListRegisterValues::ParseArgs() 1000{ 1001 m_setCmdArgs.Add(new CMICmdArgValOptionLong(m_constStrArgThread, false, false, CMICmdArgValListBase::eArgValType_Number, 1)); 1002 m_setCmdArgs.Add(new CMICmdArgValOptionLong(m_constStrArgSkip, false, false)); 1003 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgFormat, true, true)); 1004 m_setCmdArgs.Add(new CMICmdArgValListOfN(m_constStrArgRegNo, false, true, CMICmdArgValListBase::eArgValType_Number)); 1005 return ParseValidateCmdOptions(); 1006} 1007 1008//++ ------------------------------------------------------------------------------------ 1009// Details: The invoker requires this function. The command does work in this function. 1010// The command is likely to communicate with the LLDB SBDebugger in here. 1011// Type: Overridden. 1012// Args: None. 1013// Return: MIstatus::success - Functional succeeded. 1014// MIstatus::failure - Functional failed. 1015// Throws: None. 1016//-- 1017bool 1018CMICmdCmdDataListRegisterValues::Execute() 1019{ 1020 CMICMDBASE_GETOPTION(pArgFormat, String, m_constStrArgFormat); 1021 CMICMDBASE_GETOPTION(pArgRegNo, ListOfN, m_constStrArgRegNo); 1022 1023 const CMIUtilString &rStrFormat(pArgFormat->GetValue()); 1024 if (rStrFormat.length() != 1) 1025 { 1026 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_FORMAT_TYPE), m_cmdData.strMiCmd.c_str(), rStrFormat.c_str())); 1027 return MIstatus::failure; 1028 } 1029 const CMICmnLLDBDebugSessionInfoVarObj::varFormat_e eFormat = CMICmnLLDBDebugSessionInfoVarObj::GetVarFormatForChar(rStrFormat[0]); 1030 if (eFormat == CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid) 1031 { 1032 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_FORMAT_TYPE), m_cmdData.strMiCmd.c_str(), rStrFormat.c_str())); 1033 return MIstatus::failure; 1034 } 1035 1036 CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); 1037 lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); 1038 if (!sbProcess.IsValid()) 1039 { 1040 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str())); 1041 return MIstatus::failure; 1042 } 1043 1044 const CMICmdArgValListBase::VecArgObjPtr_t &rVecRegNo(pArgRegNo->GetExpectedOptions()); 1045 if (!rVecRegNo.empty()) 1046 { 1047 // List of required registers 1048 CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecRegNo.begin(); 1049 while (it != rVecRegNo.end()) 1050 { 1051 const CMICmdArgValNumber *pRegNo = static_cast<CMICmdArgValNumber *>(*it); 1052 const MIuint nRegIndex = pRegNo->GetValue(); 1053 lldb::SBValue regValue = GetRegister(nRegIndex); 1054 if (regValue.IsValid()) 1055 { 1056 AddToOutput(nRegIndex, regValue, eFormat); 1057 } 1058 1059 // Next 1060 ++it; 1061 } 1062 } 1063 else 1064 { 1065 // No register numbers are provided. Output all registers. 1066 lldb::SBThread thread = sbProcess.GetSelectedThread(); 1067 lldb::SBFrame frame = thread.GetSelectedFrame(); 1068 lldb::SBValueList registers = frame.GetRegisters(); 1069 const MIuint nRegisters = registers.GetSize(); 1070 MIuint nRegIndex = 0; 1071 for (MIuint i = 0; i < nRegisters; i++) 1072 { 1073 lldb::SBValue value = registers.GetValueAtIndex(i); 1074 const MIuint nRegChildren = value.GetNumChildren(); 1075 for (MIuint j = 0; j < nRegChildren; j++) 1076 { 1077 lldb::SBValue regValue = value.GetChildAtIndex(j); 1078 if (regValue.IsValid()) 1079 { 1080 AddToOutput(nRegIndex, regValue, eFormat); 1081 } 1082 1083 // Next 1084 ++nRegIndex; 1085 } 1086 } 1087 } 1088 1089 return MIstatus::success; 1090} 1091 1092//++ ------------------------------------------------------------------------------------ 1093// Details: The invoker requires this function. The command prepares a MI Record Result 1094// for the work carried out in the Execute(). 1095// Type: Overridden. 1096// Args: None. 1097// Return: MIstatus::success - Functional succeeded. 1098// MIstatus::failure - Functional failed. 1099// Throws: None. 1100//-- 1101bool 1102CMICmdCmdDataListRegisterValues::Acknowledge() 1103{ 1104 const CMICmnMIValueResult miValueResult("register-values", m_miValueList); 1105 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult); 1106 m_miResultRecord = miRecordResult; 1107 1108 return MIstatus::success; 1109} 1110 1111//++ ------------------------------------------------------------------------------------ 1112// Details: Required by the CMICmdFactory when registering *this command. The factory 1113// calls this function to create an instance of *this command. 1114// Type: Static method. 1115// Args: None. 1116// Return: CMICmdBase * - Pointer to a new command. 1117// Throws: None. 1118//-- 1119CMICmdBase * 1120CMICmdCmdDataListRegisterValues::CreateSelf() 1121{ 1122 return new CMICmdCmdDataListRegisterValues(); 1123} 1124 1125//++ ------------------------------------------------------------------------------------ 1126// Details: Required by the CMICmdFactory when registering *this command. The factory 1127// calls this function to create an instance of *this command. 1128// Type: Method. 1129// Args: None. 1130// Return: lldb::SBValue - LLDB SBValue object. 1131// Throws: None. 1132//-- 1133lldb::SBValue 1134CMICmdCmdDataListRegisterValues::GetRegister(const MIuint vRegisterIndex) const 1135{ 1136 lldb::SBThread thread = 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 { 1143 lldb::SBValue value = registers.GetValueAtIndex(i); 1144 const MIuint nRegChildren = value.GetNumChildren(); 1145 if (nRegisterIndex >= nRegChildren) 1146 { 1147 nRegisterIndex -= nRegChildren; 1148 continue; 1149 } 1150 1151 lldb::SBValue value2 = value.GetChildAtIndex(nRegisterIndex); 1152 if (value2.IsValid()) 1153 { 1154 return value2; 1155 } 1156 } 1157 1158 return lldb::SBValue(); 1159} 1160 1161//++ ------------------------------------------------------------------------------------ 1162// Details: Adds the register value to the output list. 1163// Type: Method. 1164// Args: Value of the register, its index and output format. 1165// Return: None 1166// Throws: None. 1167//-- 1168void 1169CMICmdCmdDataListRegisterValues::AddToOutput(const MIuint vnIndex, const lldb::SBValue &vrValue, 1170 CMICmnLLDBDebugSessionInfoVarObj::varFormat_e veVarFormat) 1171{ 1172 const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%u", vnIndex)); 1173 const CMICmnMIValueResult miValueResult("number", miValueConst); 1174 CMICmnMIValueTuple miValueTuple(miValueResult); 1175 const CMIUtilString strRegValue(CMICmnLLDBDebugSessionInfoVarObj::GetValueStringFormatted(vrValue, veVarFormat)); 1176 const CMICmnMIValueConst miValueConst2(strRegValue); 1177 const CMICmnMIValueResult miValueResult2("value", miValueConst2); 1178 miValueTuple.Add(miValueResult2); 1179 m_miValueList.Add(miValueTuple); 1180} 1181 1182//--------------------------------------------------------------------------------------- 1183//--------------------------------------------------------------------------------------- 1184//--------------------------------------------------------------------------------------- 1185 1186//++ ------------------------------------------------------------------------------------ 1187// Details: CMICmdCmdDataListRegisterChanged constructor. 1188// Type: Method. 1189// Args: None. 1190// Return: None. 1191// Throws: None. 1192//-- 1193CMICmdCmdDataListRegisterChanged::CMICmdCmdDataListRegisterChanged() 1194{ 1195 // Command factory matches this name with that received from the stdin stream 1196 m_strMiCmd = "data-list-changed-registers"; 1197 1198 // Required by the CMICmdFactory when registering *this command 1199 m_pSelfCreatorFn = &CMICmdCmdDataListRegisterChanged::CreateSelf; 1200} 1201 1202//++ ------------------------------------------------------------------------------------ 1203// Details: CMICmdCmdDataListRegisterChanged destructor. 1204// Type: Overrideable. 1205// Args: None. 1206// Return: None. 1207// Throws: None. 1208//-- 1209CMICmdCmdDataListRegisterChanged::~CMICmdCmdDataListRegisterChanged() 1210{ 1211} 1212 1213//++ ------------------------------------------------------------------------------------ 1214// Details: The invoker requires this function. The command does work in this function. 1215// The command is likely to communicate with the LLDB SBDebugger in here. 1216// Type: Overridden. 1217// Args: None. 1218// Return: MIstatus::success - Functional succeeded. 1219// MIstatus::failure - Functional failed. 1220// Throws: None. 1221//-- 1222bool 1223CMICmdCmdDataListRegisterChanged::Execute() 1224{ 1225 // Do nothing 1226 1227 return MIstatus::success; 1228} 1229 1230//++ ------------------------------------------------------------------------------------ 1231// Details: The invoker requires this function. The command prepares a MI Record Result 1232// for the work carried out in the Execute(). 1233// Type: Overridden. 1234// Args: None. 1235// Return: MIstatus::success - Functional succeeded. 1236// MIstatus::failure - Functional failed. 1237// Throws: None. 1238//-- 1239bool 1240CMICmdCmdDataListRegisterChanged::Acknowledge() 1241{ 1242 const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED)); 1243 const CMICmnMIValueResult miValueResult("msg", miValueConst); 1244 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); 1245 m_miResultRecord = miRecordResult; 1246 1247 return MIstatus::success; 1248} 1249 1250//++ ------------------------------------------------------------------------------------ 1251// Details: Required by the CMICmdFactory when registering *this command. The factory 1252// calls this function to create an instance of *this command. 1253// Type: Static method. 1254// Args: None. 1255// Return: CMICmdBase * - Pointer to a new command. 1256// Throws: None. 1257//-- 1258CMICmdBase * 1259CMICmdCmdDataListRegisterChanged::CreateSelf() 1260{ 1261 return new CMICmdCmdDataListRegisterChanged(); 1262} 1263 1264//--------------------------------------------------------------------------------------- 1265//--------------------------------------------------------------------------------------- 1266//--------------------------------------------------------------------------------------- 1267 1268//++ ------------------------------------------------------------------------------------ 1269// Details: CMICmdCmdDataWriteMemoryBytes constructor. 1270// Type: Method. 1271// Args: None. 1272// Return: None. 1273// Throws: None. 1274//-- 1275CMICmdCmdDataWriteMemoryBytes::CMICmdCmdDataWriteMemoryBytes() 1276 : m_constStrArgAddr("address") 1277 , m_constStrArgContents("contents") 1278 , m_constStrArgCount("count") 1279{ 1280 // Command factory matches this name with that received from the stdin stream 1281 m_strMiCmd = "data-write-memory-bytes"; 1282 1283 // Required by the CMICmdFactory when registering *this command 1284 m_pSelfCreatorFn = &CMICmdCmdDataWriteMemoryBytes::CreateSelf; 1285} 1286 1287//++ ------------------------------------------------------------------------------------ 1288// Details: CMICmdCmdDataWriteMemoryBytes destructor. 1289// Type: Overrideable. 1290// Args: None. 1291// Return: None. 1292// Throws: None. 1293//-- 1294CMICmdCmdDataWriteMemoryBytes::~CMICmdCmdDataWriteMemoryBytes() 1295{ 1296} 1297 1298//++ ------------------------------------------------------------------------------------ 1299// Details: The invoker requires this function. The parses the command line options 1300// arguments to extract values for each of those arguments. 1301// Type: Overridden. 1302// Args: None. 1303// Return: MIstatus::success - Functional succeeded. 1304// MIstatus::failure - Functional failed. 1305// Throws: None. 1306//-- 1307bool 1308CMICmdCmdDataWriteMemoryBytes::ParseArgs() 1309{ 1310 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgAddr, true, true, false, true)); 1311 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgContents, true, true, true, true)); 1312 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgCount, false, true, false, true)); 1313 return ParseValidateCmdOptions(); 1314} 1315 1316//++ ------------------------------------------------------------------------------------ 1317// Details: The invoker requires this function. The command does work in this function. 1318// The command is likely to communicate with the LLDB SBDebugger in here. 1319// Type: Overridden. 1320// Args: None. 1321// Return: MIstatus::success - Functional succeeded. 1322// MIstatus::failure - Functional failed. 1323// Throws: None. 1324//-- 1325bool 1326CMICmdCmdDataWriteMemoryBytes::Execute() 1327{ 1328 // Do nothing - not reproduceable (yet) in Eclipse 1329 // CMICMDBASE_GETOPTION( pArgOffset, OptionShort, m_constStrArgOffset ); 1330 // CMICMDBASE_GETOPTION( pArgAddr, String, m_constStrArgAddr ); 1331 // CMICMDBASE_GETOPTION( pArgNumber, String, m_constStrArgNumber ); 1332 // CMICMDBASE_GETOPTION( pArgContents, String, m_constStrArgContents ); 1333 // 1334 // Numbers extracts as string types as they could be hex numbers 1335 // '&' is not recognised and so has to be removed 1336 1337 return MIstatus::success; 1338} 1339 1340//++ ------------------------------------------------------------------------------------ 1341// Details: The invoker requires this function. The command prepares a MI Record Result 1342// for the work carried out in the Execute(). 1343// Type: Overridden. 1344// Args: None. 1345// Return: MIstatus::success - Functional succeeded. 1346// MIstatus::failure - Functional failed. 1347// Throws: None. 1348//-- 1349bool 1350CMICmdCmdDataWriteMemoryBytes::Acknowledge() 1351{ 1352 const CMICmnMIValueConst miValueConst(MIRSRC(IDS_WORD_NOT_IMPLEMENTED)); 1353 const CMICmnMIValueResult miValueResult("msg", miValueConst); 1354 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); 1355 m_miResultRecord = miRecordResult; 1356 1357 return MIstatus::success; 1358} 1359 1360//++ ------------------------------------------------------------------------------------ 1361// Details: Required by the CMICmdFactory when registering *this command. The factory 1362// calls this function to create an instance of *this command. 1363// Type: Static method. 1364// Args: None. 1365// Return: CMICmdBase * - Pointer to a new command. 1366// Throws: None. 1367//-- 1368CMICmdBase * 1369CMICmdCmdDataWriteMemoryBytes::CreateSelf() 1370{ 1371 return new CMICmdCmdDataWriteMemoryBytes(); 1372} 1373 1374//--------------------------------------------------------------------------------------- 1375//--------------------------------------------------------------------------------------- 1376//--------------------------------------------------------------------------------------- 1377 1378//++ ------------------------------------------------------------------------------------ 1379// Details: CMICmdCmdDataWriteMemory constructor. 1380// Type: Method. 1381// Args: None. 1382// Return: None. 1383// Throws: None. 1384//-- 1385CMICmdCmdDataWriteMemory::CMICmdCmdDataWriteMemory() 1386 : m_constStrArgOffset("o") 1387 , m_constStrArgAddr("address") 1388 , m_constStrArgD("d") 1389 , m_constStrArgNumber("a number") 1390 , m_constStrArgContents("contents") 1391 , m_nAddr(0) 1392 , m_nCount(0) 1393 , m_pBufferMemory(nullptr) 1394{ 1395 // Command factory matches this name with that received from the stdin stream 1396 m_strMiCmd = "data-write-memory"; 1397 1398 // Required by the CMICmdFactory when registering *this command 1399 m_pSelfCreatorFn = &CMICmdCmdDataWriteMemory::CreateSelf; 1400} 1401 1402//++ ------------------------------------------------------------------------------------ 1403// Details: CMICmdCmdDataWriteMemory destructor. 1404// Type: Overrideable. 1405// Args: None. 1406// Return: None. 1407// Throws: None. 1408//-- 1409CMICmdCmdDataWriteMemory::~CMICmdCmdDataWriteMemory() 1410{ 1411 if (m_pBufferMemory != nullptr) 1412 { 1413 delete[] m_pBufferMemory; 1414 m_pBufferMemory = nullptr; 1415 } 1416} 1417 1418//++ ------------------------------------------------------------------------------------ 1419// Details: The invoker requires this function. The parses the command line options 1420// arguments to extract values for each of those arguments. 1421// Type: Overridden. 1422// Args: None. 1423// Return: MIstatus::success - Functional succeeded. 1424// MIstatus::failure - Functional failed. 1425// Throws: None. 1426//-- 1427bool 1428CMICmdCmdDataWriteMemory::ParseArgs() 1429{ 1430 m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgOffset, false, true, CMICmdArgValListBase::eArgValType_Number, 1)); 1431 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgAddr, true, true)); 1432 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgD, true, true)); 1433 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumber, true, true)); 1434 m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgContents, true, true)); 1435 return ParseValidateCmdOptions(); 1436} 1437 1438//++ ------------------------------------------------------------------------------------ 1439// Details: The invoker requires this function. The command does work in this function. 1440// The command is likely to communicate with the LLDB SBDebugger in here. 1441// Type: Overridden. 1442// Args: None. 1443// Return: MIstatus::success - Functional succeeded. 1444// MIstatus::failure - Functional failed. 1445// Throws: None. 1446//-- 1447bool 1448CMICmdCmdDataWriteMemory::Execute() 1449{ 1450 CMICMDBASE_GETOPTION(pArgOffset, OptionShort, m_constStrArgOffset); 1451 CMICMDBASE_GETOPTION(pArgAddr, Number, m_constStrArgAddr); 1452 CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNumber); 1453 CMICMDBASE_GETOPTION(pArgContents, Number, m_constStrArgContents); 1454 1455 MIuint nAddrOffset = 0; 1456 if (pArgOffset->GetFound() && !pArgOffset->GetExpectedOption<CMICmdArgValNumber, MIuint>(nAddrOffset)) 1457 { 1458 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ARGS_ERR_VALIDATION_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgAddr.c_str())); 1459 return MIstatus::failure; 1460 } 1461 m_nAddr = pArgAddr->GetValue(); 1462 m_nCount = pArgNumber->GetValue(); 1463 const MIuint64 nValue = pArgContents->GetValue(); 1464 1465 m_pBufferMemory = new unsigned char[m_nCount]; 1466 if (m_pBufferMemory == nullptr) 1467 { 1468 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_MEMORY_ALLOC_FAILURE), m_cmdData.strMiCmd.c_str(), m_nCount)); 1469 return MIstatus::failure; 1470 } 1471 *m_pBufferMemory = static_cast<char>(nValue); 1472 1473 CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); 1474 lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); 1475 lldb::SBError error; 1476 lldb::addr_t addr = static_cast<lldb::addr_t>(m_nAddr + nAddrOffset); 1477 const size_t nBytesWritten = sbProcess.WriteMemory(addr, (const void *)m_pBufferMemory, (size_t)m_nCount, error); 1478 if (nBytesWritten != static_cast<size_t>(m_nCount)) 1479 { 1480 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_NOT_WRITE_WHOLEBLK), m_cmdData.strMiCmd.c_str(), m_nCount, addr)); 1481 return MIstatus::failure; 1482 } 1483 if (error.Fail()) 1484 { 1485 lldb::SBStream err; 1486 const bool bOk = error.GetDescription(err); 1487 MIunused(bOk); 1488 SetError( 1489 CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDB_ERR_WRITE_MEM_BYTES), m_cmdData.strMiCmd.c_str(), m_nCount, addr, err.GetData())); 1490 return MIstatus::failure; 1491 } 1492 1493 return MIstatus::success; 1494} 1495 1496//++ ------------------------------------------------------------------------------------ 1497// Details: The invoker requires this function. The command prepares a MI Record Result 1498// for the work carried out in the Execute(). 1499// Type: Overridden. 1500// Args: None. 1501// Return: MIstatus::success - Functional succeeded. 1502// MIstatus::failure - Functional failed. 1503// Throws: None. 1504//-- 1505bool 1506CMICmdCmdDataWriteMemory::Acknowledge() 1507{ 1508 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); 1509 m_miResultRecord = miRecordResult; 1510 1511 return MIstatus::success; 1512} 1513 1514//++ ------------------------------------------------------------------------------------ 1515// Details: Required by the CMICmdFactory when registering *this command. The factory 1516// calls this function to create an instance of *this command. 1517// Type: Static method. 1518// Args: None. 1519// Return: CMICmdBase * - Pointer to a new command. 1520// Throws: None. 1521//-- 1522CMICmdBase * 1523CMICmdCmdDataWriteMemory::CreateSelf() 1524{ 1525 return new CMICmdCmdDataWriteMemory(); 1526} 1527 1528//--------------------------------------------------------------------------------------- 1529//--------------------------------------------------------------------------------------- 1530//--------------------------------------------------------------------------------------- 1531 1532//++ ------------------------------------------------------------------------------------ 1533// Details: CMICmdCmdDataInfoLine constructor. 1534// Type: Method. 1535// Args: None. 1536// Return: None. 1537// Throws: None. 1538//-- 1539CMICmdCmdDataInfoLine::CMICmdCmdDataInfoLine() 1540 : m_constStrArgLocation("location") 1541{ 1542 // Command factory matches this name with that received from the stdin stream 1543 m_strMiCmd = "data-info-line"; 1544 1545 // Required by the CMICmdFactory when registering *this command 1546 m_pSelfCreatorFn = &CMICmdCmdDataInfoLine::CreateSelf; 1547} 1548 1549//++ ------------------------------------------------------------------------------------ 1550// Details: CMICmdCmdDataInfoLine destructor. 1551// Type: Overrideable. 1552// Args: None. 1553// Return: None. 1554// Throws: None. 1555//-- 1556CMICmdCmdDataInfoLine::~CMICmdCmdDataInfoLine() 1557{ 1558} 1559 1560//++ ------------------------------------------------------------------------------------ 1561// Details: The invoker requires this function. The parses the command line options 1562// arguments to extract values for each of those arguments. 1563// Type: Overridden. 1564// Args: None. 1565// Return: MIstatus::success - Functional succeeded. 1566// MIstatus::failure - Functional failed. 1567// Throws: None. 1568//-- 1569bool 1570CMICmdCmdDataInfoLine::ParseArgs() 1571{ 1572 m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgLocation, true, true)); 1573 return ParseValidateCmdOptions(); 1574} 1575 1576//++ ------------------------------------------------------------------------------------ 1577// Details: The invoker requires this function. The command does work in this function. 1578// The command is likely to communicate with the LLDB SBDebugger in here. 1579// Type: Overridden. 1580// Args: None. 1581// Return: MIstatus::success - Functional succeeded. 1582// MIstatus::failure - Functional failed. 1583// Throws: None. 1584//-- 1585bool 1586CMICmdCmdDataInfoLine::Execute() 1587{ 1588 CMICMDBASE_GETOPTION(pArgLocation, String, m_constStrArgLocation); 1589 1590 const CMIUtilString &strLocation(pArgLocation->GetValue()); 1591 CMIUtilString strCmdOptionsLocation; 1592 if (strLocation.at(0) == '*') 1593 { 1594 // Parse argument: 1595 // *0x12345 1596 // ^^^^^^^ -- address 1597 const CMIUtilString strAddress(strLocation.substr(1)); 1598 strCmdOptionsLocation = CMIUtilString::Format("--address %s", strAddress.c_str()); 1599 } 1600 else 1601 { 1602 const size_t nLineStartPos = strLocation.rfind(':'); 1603 if ((nLineStartPos == std::string::npos) || (nLineStartPos == 0) || (nLineStartPos == strLocation.length() - 1)) 1604 { 1605 SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_LOCATION_FORMAT), m_cmdData.strMiCmd.c_str(), strLocation.c_str()) 1606 .c_str()); 1607 return MIstatus::failure; 1608 } 1609 // Parse argument: 1610 // hello.cpp:5 1611 // ^^^^^^^^^ -- file 1612 // ^ -- line 1613 const CMIUtilString strFile(strLocation.substr(0, nLineStartPos)); 1614 const CMIUtilString strLine(strLocation.substr(nLineStartPos + 1)); 1615 strCmdOptionsLocation = CMIUtilString::Format("--file \"%s\" --line %s", strFile.AddSlashes().c_str(), strLine.c_str()); 1616 } 1617 const CMIUtilString strCmd(CMIUtilString::Format("target modules lookup -v %s", strCmdOptionsLocation.c_str())); 1618 1619 CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); 1620 const lldb::ReturnStatus rtn = rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult); 1621 MIunused(rtn); 1622 1623 return MIstatus::success; 1624} 1625 1626//++ ------------------------------------------------------------------------------------ 1627// Details: Helper function for parsing a line entry returned from lldb for the command: 1628// target modules lookup -v <location> 1629// where the line entry is of the format: 1630// LineEntry: \[0x0000000100000f37-0x0000000100000f45\): /path/file:3[:1] 1631// start end file line column(opt) 1632// Args: input - (R) Input string to parse. 1633// start - (W) String representing the start address. 1634// end - (W) String representing the end address. 1635// file - (W) String representing the file. 1636// line - (W) String representing the line. 1637// Return: bool - True = input was parsed successfully, false = input could not be parsed. 1638// Throws: None. 1639//-- 1640static bool 1641ParseLLDBLineEntry(const char *input, CMIUtilString &start, CMIUtilString &end, 1642 CMIUtilString &file, CMIUtilString &line) 1643{ 1644 // Note: Ambiguities arise because the column is optional, and 1645 // because : can appear in filenames or as a byte in a multibyte 1646 // UTF8 character. We keep those cases to a minimum by using regex 1647 // to work on the string from both the left and right, so that what 1648 // is remains is assumed to be the filename. 1649 1650 // Match LineEntry using regex. 1651 static MIUtilParse::CRegexParser g_lineentry_nocol_regex( 1652 "^ *LineEntry: \\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+)$"); 1653 static MIUtilParse::CRegexParser g_lineentry_col_regex( 1654 "^ *LineEntry: \\[(0x[0-9a-fA-F]+)-(0x[0-9a-fA-F]+)\\): (.+):([0-9]+):[0-9]+$"); 1655 // ^1=start ^2=end ^3=f ^4=line ^5=:col(opt) 1656 1657 MIUtilParse::CRegexParser::Match match(6); 1658 1659 // First try matching the LineEntry with the column, 1660 // then try without the column. 1661 const bool ok = g_lineentry_col_regex.Execute(input, match) || 1662 g_lineentry_nocol_regex.Execute(input, match); 1663 if (ok) 1664 { 1665 start = match.GetMatchAtIndex(1); 1666 end = match.GetMatchAtIndex(2); 1667 file = match.GetMatchAtIndex(3); 1668 line = match.GetMatchAtIndex(4); 1669 } 1670 return ok; 1671} 1672 1673//++ ------------------------------------------------------------------------------------ 1674// Details: The invoker requires this function. The command prepares a MI Record Result 1675// for the work carried out in the Execute(). 1676// Type: Overridden. 1677// Args: None. 1678// Return: MIstatus::success - Functional succeeded. 1679// MIstatus::failure - Functional failed. 1680// Throws: None. 1681//-- 1682bool 1683CMICmdCmdDataInfoLine::Acknowledge() 1684{ 1685 if (m_lldbResult.GetErrorSize() > 0) 1686 { 1687 const CMICmnMIValueConst miValueConst(m_lldbResult.GetError()); 1688 const CMICmnMIValueResult miValueResult("msg", miValueConst); 1689 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); 1690 m_miResultRecord = miRecordResult; 1691 return MIstatus::success; 1692 } 1693 else if (m_lldbResult.GetOutputSize() > 0) 1694 { 1695 CMIUtilString::VecString_t vecLines; 1696 const CMIUtilString strLldbMsg(m_lldbResult.GetOutput()); 1697 const MIuint nLines(strLldbMsg.SplitLines(vecLines)); 1698 1699 for (MIuint i = 0; i < nLines; ++i) 1700 { 1701 // String looks like: 1702 // LineEntry: \[0x0000000100000f37-0x0000000100000f45\): /path/to/file:3[:1] 1703 const CMIUtilString &rLine(vecLines[i]); 1704 CMIUtilString strStart; 1705 CMIUtilString strEnd; 1706 CMIUtilString strFile; 1707 CMIUtilString strLine; 1708 1709 if (!ParseLLDBLineEntry(rLine.c_str(), strStart, strEnd, strFile, strLine)) 1710 continue; 1711 1712 const CMICmnMIValueConst miValueConst(strStart); 1713 const CMICmnMIValueResult miValueResult("start", miValueConst); 1714 CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, 1715 CMICmnMIResultRecord::eResultClass_Done, 1716 miValueResult); 1717 const CMICmnMIValueConst miValueConst2(strEnd); 1718 const CMICmnMIValueResult miValueResult2("end", miValueConst2); 1719 miRecordResult.Add(miValueResult2); 1720 const CMICmnMIValueConst miValueConst3(strFile); 1721 const CMICmnMIValueResult miValueResult3("file", miValueConst3); 1722 miRecordResult.Add(miValueResult3); 1723 const CMICmnMIValueConst miValueConst4(strLine); 1724 const CMICmnMIValueResult miValueResult4("line", miValueConst4); 1725 miRecordResult.Add(miValueResult4); 1726 1727 // MI print "%s^done,start=\"%d\",end=\"%d\"",file=\"%s\",line=\"%d\" 1728 m_miResultRecord = miRecordResult; 1729 1730 return MIstatus::success; 1731 } 1732 } 1733 1734 // MI print "%s^error,msg=\"Command '-data-info-line'. Error: The LineEntry is absent or has an unknown format.\"" 1735 const CMICmnMIValueConst miValueConst(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SOME_ERROR), m_cmdData.strMiCmd.c_str(), "The LineEntry is absent or has an unknown format.")); 1736 const CMICmnMIValueResult miValueResult("msg", miValueConst); 1737 const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); 1738 m_miResultRecord = miRecordResult; 1739 1740 return MIstatus::success; 1741} 1742 1743//++ ------------------------------------------------------------------------------------ 1744// Details: Required by the CMICmdFactory when registering *this command. The factory 1745// calls this function to create an instance of *this command. 1746// Type: Static method. 1747// Args: None. 1748// Return: CMICmdBase * - Pointer to a new command. 1749// Throws: None. 1750//-- 1751CMICmdBase * 1752CMICmdCmdDataInfoLine::CreateSelf() 1753{ 1754 return new CMICmdCmdDataInfoLine(); 1755} 1756