//===-- MICmdCmdExec.cpp ----------------------------------------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // Overview: CMICmdCmdExecRun implementation. // CMICmdCmdExecContinue implementation. // CMICmdCmdExecNext implementation. // CMICmdCmdExecStep implementation. // CMICmdCmdExecNextInstruction implementation. // CMICmdCmdExecStepInstruction implementation. // CMICmdCmdExecFinish implementation. // CMICmdCmdExecInterrupt implementation. // CMICmdCmdExecArguments implementation. // CMICmdCmdExecAbort implementation. // Third Party Headers: #include "lldb/API/SBCommandInterpreter.h" #include "lldb/API/SBProcess.h" #include "lldb/API/SBStream.h" #include "lldb/API/SBThread.h" #include "lldb/lldb-enumerations.h" // In-house headers: #include "MICmdArgValListOfN.h" #include "MICmdArgValNumber.h" #include "MICmdArgValOptionLong.h" #include "MICmdArgValOptionShort.h" #include "MICmdArgValString.h" #include "MICmdArgValThreadGrp.h" #include "MICmdCmdExec.h" #include "MICmnLLDBDebugSessionInfo.h" #include "MICmnLLDBDebugger.h" #include "MICmnMIOutOfBandRecord.h" #include "MICmnMIResultRecord.h" #include "MICmnMIValueConst.h" #include "MICmnStreamStdout.h" #include "MIDriver.h" //++ // Details: CMICmdCmdExecRun constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdExecRun::CMICmdCmdExecRun() : m_constStrArgStart("start") { // Command factory matches this name with that received from the stdin stream m_strMiCmd = "exec-run"; // Required by the CMICmdFactory when registering *this command m_pSelfCreatorFn = &CMICmdCmdExecRun::CreateSelf; } //++ // Details: CMICmdCmdExecRun destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdExecRun::~CMICmdCmdExecRun() {} //++ // Details: The invoker requires this function. It parses the command line // options' // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdExecRun::ParseArgs() { m_setCmdArgs.Add(new CMICmdArgValOptionLong( m_constStrArgStart, false, true, CMICmdArgValListBase::eArgValType_OptionLong, 0)); return ParseValidateCmdOptions(); } //++ // Details: The invoker requires this function. The command does work in this // function. // The command is likely to communicate with the LLDB SBDebugger in // here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdExecRun::Execute() { CMICmnLLDBDebugSessionInfo &rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance()); { // Check we have a valid target. // Note: target created via 'file-exec-and-symbols' command. lldb::SBTarget sbTarget = rSessionInfo.GetTarget(); if (!sbTarget.IsValid() || sbTarget == rSessionInfo.GetDebugger().GetDummyTarget()) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_CURRENT), m_cmdData.strMiCmd.c_str())); return MIstatus::failure; } } lldb::SBError error; lldb::SBStream errMsg; lldb::SBLaunchInfo launchInfo = rSessionInfo.GetTarget().GetLaunchInfo(); launchInfo.SetListener(rSessionInfo.GetListener()); // Run to first instruction or main() requested? CMICMDBASE_GETOPTION(pArgStart, OptionLong, m_constStrArgStart); if (pArgStart->GetFound()) { launchInfo.SetLaunchFlags(launchInfo.GetLaunchFlags() | lldb::eLaunchFlagStopAtEntry); } lldb::SBProcess process = rSessionInfo.GetTarget().Launch(launchInfo, error); if (!process.IsValid()) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str(), errMsg.GetData())); return MIstatus::failure; } const auto successHandler = [this] { if (!CMIDriver::Instance().SetDriverStateRunningDebugging()) { const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription()); SetError(CMIUtilString::Format( MIRSRC(IDS_CMD_ERR_SET_NEW_DRIVER_STATE), m_cmdData.strMiCmd.c_str(), rErrMsg.c_str())); return MIstatus::failure; } return MIstatus::success; }; return HandleSBErrorWithSuccess(error, successHandler); } //++ // Details: The invoker requires this function. The command prepares a MI Record // Result // for the work carried out in the Execute(). // Called only if Execute() set status as successful on completion. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdExecRun::Acknowledge() { m_miResultRecord = CMICmnMIResultRecord( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); CMICmnLLDBDebugSessionInfo &rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance()); lldb::pid_t pid = rSessionInfo.GetProcess().GetProcessID(); // Give the client '=thread-group-started,id="i1" pid="xyz"' m_bHasResultRecordExtra = true; const CMICmnMIValueConst miValueConst2("i1"); const CMICmnMIValueResult miValueResult2("id", miValueConst2); const CMIUtilString strPid(CMIUtilString::Format("%lld", pid)); const CMICmnMIValueConst miValueConst(strPid); const CMICmnMIValueResult miValueResult("pid", miValueConst); CMICmnMIOutOfBandRecord miOutOfBand( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, miValueResult2); miOutOfBand.Add(miValueResult); m_miResultRecordExtra = miOutOfBand.GetString(); return MIstatus::success; } //++ // Details: Required by the CMICmdFactory when registering *this command. The // factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- CMICmdBase *CMICmdCmdExecRun::CreateSelf() { return new CMICmdCmdExecRun(); } //++ // Details: CMICmdCmdExecContinue constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdExecContinue::CMICmdCmdExecContinue() { // Command factory matches this name with that received from the stdin stream m_strMiCmd = "exec-continue"; // Required by the CMICmdFactory when registering *this command m_pSelfCreatorFn = &CMICmdCmdExecContinue::CreateSelf; } //++ // Details: CMICmdCmdExecContinue destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdExecContinue::~CMICmdCmdExecContinue() {} //++ // Details: The invoker requires this function. The command does work in this // function. // The command is likely to communicate with the LLDB SBDebugger in // here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdExecContinue::Execute() { const auto successHandler = [this] { // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM if (!CMIDriver::Instance().SetDriverStateRunningDebugging()) { const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription()); SetError(CMIUtilString::Format( MIRSRC(IDS_CMD_ERR_SET_NEW_DRIVER_STATE), m_cmdData.strMiCmd.c_str(), rErrMsg.c_str())); return MIstatus::failure; } return MIstatus::success; }; return HandleSBErrorWithSuccess( CMICmnLLDBDebugSessionInfo::Instance().GetProcess().Continue(), successHandler); } //++ // Details: The invoker requires this function. The command prepares a MI Record // Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdExecContinue::Acknowledge() { m_miResultRecord = CMICmnMIResultRecord( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); return MIstatus::success; } //++ // Details: Required by the CMICmdFactory when registering *this command. The // factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- CMICmdBase *CMICmdCmdExecContinue::CreateSelf() { return new CMICmdCmdExecContinue(); } //++ // Details: CMICmdCmdExecNext constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdExecNext::CMICmdCmdExecNext() : m_constStrArgNumber("number") { // Command factory matches this name with that received from the stdin stream m_strMiCmd = "exec-next"; // Required by the CMICmdFactory when registering *this command m_pSelfCreatorFn = &CMICmdCmdExecNext::CreateSelf; } //++ // Details: CMICmdCmdExecNext destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdExecNext::~CMICmdCmdExecNext() {} //++ // Details: The invoker requires this function. The parses the command line // options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdExecNext::ParseArgs() { m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumber, false, false)); return ParseValidateCmdOptions(); } //++ // Details: The invoker requires this function. The command does work in this // function. // The command is likely to communicate with the LLDB SBDebugger in // here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdExecNext::Execute() { CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); // Retrieve the --thread option's thread ID (only 1) MIuint64 nThreadId = UINT64_MAX; if (pArgThread->GetFound() && !pArgThread->GetExpectedOption(nThreadId)) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); return MIstatus::failure; } CMICmnLLDBDebugSessionInfo &rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBError error; if (nThreadId != UINT64_MAX) { lldb::SBThread sbThread = rSessionInfo.GetProcess().GetThreadByIndexID(nThreadId); if (!sbThread.IsValid()) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); return MIstatus::failure; } sbThread.StepOver(lldb::eOnlyDuringStepping, error); } else rSessionInfo.GetProcess().GetSelectedThread().StepOver( lldb::eOnlyDuringStepping, error); return HandleSBError(error); } //++ // Details: The invoker requires this function. The command prepares a MI Record // Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdExecNext::Acknowledge() { m_miResultRecord = CMICmnMIResultRecord( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); return MIstatus::success; } //++ // Details: Required by the CMICmdFactory when registering *this command. The // factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- CMICmdBase *CMICmdCmdExecNext::CreateSelf() { return new CMICmdCmdExecNext(); } //++ // Details: CMICmdCmdExecStep constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdExecStep::CMICmdCmdExecStep() : m_constStrArgNumber("number") { // Command factory matches this name with that received from the stdin stream m_strMiCmd = "exec-step"; // Required by the CMICmdFactory when registering *this command m_pSelfCreatorFn = &CMICmdCmdExecStep::CreateSelf; } //++ // Details: CMICmdCmdExecStep destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdExecStep::~CMICmdCmdExecStep() {} //++ // Details: The invoker requires this function. The parses the command line // options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdExecStep::ParseArgs() { m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumber, false, false)); return ParseValidateCmdOptions(); } //++ // Details: The invoker requires this function. The command does work in this // function. // The command is likely to communicate with the LLDB SBDebugger in // here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdExecStep::Execute() { CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); // Retrieve the --thread option's thread ID (only 1) MIuint64 nThreadId = UINT64_MAX; if (pArgThread->GetFound() && !pArgThread->GetExpectedOption(nThreadId)) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); return MIstatus::failure; } CMICmnLLDBDebugSessionInfo &rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBError error; if (nThreadId != UINT64_MAX) { lldb::SBThread sbThread = rSessionInfo.GetProcess().GetThreadByIndexID(nThreadId); if (!sbThread.IsValid()) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); return MIstatus::failure; } sbThread.StepInto(nullptr, LLDB_INVALID_LINE_NUMBER, error); } else rSessionInfo.GetProcess().GetSelectedThread().StepInto( nullptr, LLDB_INVALID_LINE_NUMBER, error); return HandleSBError(error); } //++ // Details: The invoker requires this function. The command prepares a MI Record // Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdExecStep::Acknowledge() { m_miResultRecord = CMICmnMIResultRecord( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); return MIstatus::success; } //++ // Details: Required by the CMICmdFactory when registering *this command. The // factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- CMICmdBase *CMICmdCmdExecStep::CreateSelf() { return new CMICmdCmdExecStep(); } //++ // Details: CMICmdCmdExecNextInstruction constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdExecNextInstruction::CMICmdCmdExecNextInstruction() : m_constStrArgNumber("number") { // Command factory matches this name with that received from the stdin stream m_strMiCmd = "exec-next-instruction"; // Required by the CMICmdFactory when registering *this command m_pSelfCreatorFn = &CMICmdCmdExecNextInstruction::CreateSelf; } //++ // Details: CMICmdCmdExecNextInstruction destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdExecNextInstruction::~CMICmdCmdExecNextInstruction() {} //++ // Details: The invoker requires this function. The parses the command line // options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdExecNextInstruction::ParseArgs() { m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumber, false, false)); return ParseValidateCmdOptions(); } //++ // Details: The invoker requires this function. The command does work in this // function. // The command is likely to communicate with the LLDB SBDebugger in // here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdExecNextInstruction::Execute() { CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); // Retrieve the --thread option's thread ID (only 1) MIuint64 nThreadId = UINT64_MAX; if (pArgThread->GetFound() && !pArgThread->GetExpectedOption(nThreadId)) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); return MIstatus::failure; } CMICmnLLDBDebugSessionInfo &rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBError error; if (nThreadId != UINT64_MAX) { lldb::SBThread sbThread = rSessionInfo.GetProcess().GetThreadByIndexID(nThreadId); if (!sbThread.IsValid()) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); return MIstatus::failure; } sbThread.StepInstruction(true, error); } else rSessionInfo.GetProcess().GetSelectedThread().StepInstruction( true, error); return HandleSBError(error); } //++ // Details: The invoker requires this function. The command prepares a MI Record // Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdExecNextInstruction::Acknowledge() { m_miResultRecord = CMICmnMIResultRecord( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); return MIstatus::success; } //++ // Details: Required by the CMICmdFactory when registering *this command. The // factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- CMICmdBase *CMICmdCmdExecNextInstruction::CreateSelf() { return new CMICmdCmdExecNextInstruction(); } //++ // Details: CMICmdCmdExecStepInstruction constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdExecStepInstruction::CMICmdCmdExecStepInstruction() : m_constStrArgNumber("number") { // Command factory matches this name with that received from the stdin stream m_strMiCmd = "exec-step-instruction"; // Required by the CMICmdFactory when registering *this command m_pSelfCreatorFn = &CMICmdCmdExecStepInstruction::CreateSelf; } //++ // Details: CMICmdCmdExecStepInstruction destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdExecStepInstruction::~CMICmdCmdExecStepInstruction() {} //++ // Details: The invoker requires this function. The parses the command line // options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdExecStepInstruction::ParseArgs() { m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNumber, false, false)); return ParseValidateCmdOptions(); } //++ // Details: The invoker requires this function. The command does work in this // function. // The command is likely to communicate with the LLDB SBDebugger in // here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdExecStepInstruction::Execute() { CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); // Retrieve the --thread option's thread ID (only 1) MIuint64 nThreadId = UINT64_MAX; if (pArgThread->GetFound() && !pArgThread->GetExpectedOption(nThreadId)) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); return MIstatus::failure; } CMICmnLLDBDebugSessionInfo &rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBError error; if (nThreadId != UINT64_MAX) { lldb::SBThread sbThread = rSessionInfo.GetProcess().GetThreadByIndexID(nThreadId); if (!sbThread.IsValid()) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); return MIstatus::failure; } sbThread.StepInstruction(false, error); } else rSessionInfo.GetProcess().GetSelectedThread().StepInstruction( false, error); return HandleSBError(error); } //++ // Details: The invoker requires this function. The command prepares a MI Record // Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdExecStepInstruction::Acknowledge() { m_miResultRecord = CMICmnMIResultRecord( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); return MIstatus::success; } //++ // Details: Required by the CMICmdFactory when registering *this command. The // factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- CMICmdBase *CMICmdCmdExecStepInstruction::CreateSelf() { return new CMICmdCmdExecStepInstruction(); } //++ // Details: CMICmdCmdExecFinish constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdExecFinish::CMICmdCmdExecFinish() { // Command factory matches this name with that received from the stdin stream m_strMiCmd = "exec-finish"; // Required by the CMICmdFactory when registering *this command m_pSelfCreatorFn = &CMICmdCmdExecFinish::CreateSelf; } //++ // Details: CMICmdCmdExecFinish destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdExecFinish::~CMICmdCmdExecFinish() {} //++ // Details: The invoker requires this function. The parses the command line // options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdExecFinish::ParseArgs() { return ParseValidateCmdOptions(); } //++ // Details: The invoker requires this function. The command does work in this // function. // The command is likely to communicate with the LLDB SBDebugger in // here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdExecFinish::Execute() { CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); // Retrieve the --thread option's thread ID (only 1) MIuint64 nThreadId = UINT64_MAX; if (pArgThread->GetFound() && !pArgThread->GetExpectedOption(nThreadId)) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_OPTION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); return MIstatus::failure; } CMICmnLLDBDebugSessionInfo &rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBError error; if (nThreadId != UINT64_MAX) { lldb::SBThread sbThread = rSessionInfo.GetProcess().GetThreadByIndexID(nThreadId); if (!sbThread.IsValid()) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str())); return MIstatus::failure; } sbThread.StepOut(error); } else rSessionInfo.GetProcess().GetSelectedThread().StepOut(error); return HandleSBError(error); } //++ // Details: The invoker requires this function. The command prepares a MI Record // Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdExecFinish::Acknowledge() { m_miResultRecord = CMICmnMIResultRecord( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); return MIstatus::success; } //++ // Details: Required by the CMICmdFactory when registering *this command. The // factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- CMICmdBase *CMICmdCmdExecFinish::CreateSelf() { return new CMICmdCmdExecFinish(); } //++ // Details: CMICmdCmdExecInterrupt constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdExecInterrupt::CMICmdCmdExecInterrupt() { // Command factory matches this name with that received from the stdin stream m_strMiCmd = "exec-interrupt"; // Required by the CMICmdFactory when registering *this command m_pSelfCreatorFn = &CMICmdCmdExecInterrupt::CreateSelf; } //++ // Details: CMICmdCmdExecInterrupt destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdExecInterrupt::~CMICmdCmdExecInterrupt() {} //++ // Details: The invoker requires this function. The command does work in this // function. // The command is likely to communicate with the LLDB SBDebugger in // here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdExecInterrupt::Execute() { const auto successHandler = [this] { // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM if (!CMIDriver::Instance().SetDriverStateRunningNotDebugging()) { const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription()); SetErrorDescription(CMIUtilString::Format( MIRSRC(IDS_CMD_ERR_SET_NEW_DRIVER_STATE), m_cmdData.strMiCmd.c_str(), rErrMsg.c_str())); return MIstatus::failure; } return MIstatus::success; }; return HandleSBErrorWithSuccess( CMICmnLLDBDebugSessionInfo::Instance().GetProcess().Stop(), successHandler); } //++ // Details: The invoker requires this function. The command prepares a MI Record // Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdExecInterrupt::Acknowledge() { m_miResultRecord = CMICmnMIResultRecord( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); return MIstatus::success; } //++ // Details: Required by the CMICmdFactory when registering *this command. The // factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- CMICmdBase *CMICmdCmdExecInterrupt::CreateSelf() { return new CMICmdCmdExecInterrupt(); } //++ // Details: CMICmdCmdExecArguments constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdExecArguments::CMICmdCmdExecArguments() : m_constStrArgArguments("arguments") { // Command factory matches this name with that received from the stdin stream m_strMiCmd = "exec-arguments"; // Required by the CMICmdFactory when registering *this command m_pSelfCreatorFn = &CMICmdCmdExecArguments::CreateSelf; } //++ // Details: CMICmdCmdExecArguments destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdExecArguments::~CMICmdCmdExecArguments() {} //++ // Details: The invoker requires this function. The parses the command line // options // arguments to extract values for each of those arguments. // Type: Overridden. // Args: None. // Return: MIstatus::success - Function succeeded. // MIstatus::failure - Function failed. // Throws: None. //-- bool CMICmdCmdExecArguments::ParseArgs() { m_setCmdArgs.Add(new CMICmdArgValListOfN( m_constStrArgArguments, false, true, CMICmdArgValListBase::eArgValType_StringAnything)); return ParseValidateCmdOptions(); } //++ // Details: The invoker requires this function. The command does work in this // function. // The command is likely to communicate with the LLDB SBDebugger in // here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Function succeeded. // MIstatus::failure - Function failed. // Throws: None. //-- bool CMICmdCmdExecArguments::Execute() { CMICMDBASE_GETOPTION(pArgArguments, ListOfN, m_constStrArgArguments); CMICmnLLDBDebugSessionInfo &rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBTarget sbTarget = rSessionInfo.GetTarget(); if (!sbTarget.IsValid()) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_CURRENT), m_cmdData.strMiCmd.c_str())); return MIstatus::failure; } lldb::SBLaunchInfo sbLaunchInfo = sbTarget.GetLaunchInfo(); sbLaunchInfo.SetArguments(nullptr, false); CMIUtilString strArg; size_t nArgIndex = 0; while (pArgArguments->GetExpectedOption( strArg, nArgIndex)) { const char *argv[2] = {strArg.c_str(), nullptr}; sbLaunchInfo.SetArguments(argv, true); ++nArgIndex; } sbTarget.SetLaunchInfo(sbLaunchInfo); return MIstatus::success; } //++ // Details: The invoker requires this function. The command prepares a MI Record // Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. // Return: MIstatus::success - Function succeeded. // MIstatus::failure - Function failed. // Throws: None. //-- bool CMICmdCmdExecArguments::Acknowledge() { m_miResultRecord = CMICmnMIResultRecord( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); return MIstatus::success; } //++ // Details: Required by the CMICmdFactory when registering *this command. The // factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- CMICmdBase *CMICmdCmdExecArguments::CreateSelf() { return new CMICmdCmdExecArguments(); } //++ // Details: CMICmdCmdExecAbort constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdExecAbort::CMICmdCmdExecAbort() { // Command factory matches this name with that received from the stdin stream m_strMiCmd = "exec-abort"; // Required by the CMICmdFactory when registering *this command m_pSelfCreatorFn = &CMICmdCmdExecAbort::CreateSelf; } //++ // Details: CMICmdCmdExecAbort destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdExecAbort::~CMICmdCmdExecAbort() {} //++ // Details: The invoker requires this function. The command does work in this // function. // The command is likely to communicate with the LLDB SBDebugger in // here. // Type: Overridden. // Args: None. // Return: MIstatus::success - Function succeeded. // MIstatus::failure - Function failed. // Throws: None. //-- bool CMICmdCmdExecAbort::Execute() { CMICmnLLDBDebugSessionInfo &rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); if (!sbProcess.IsValid()) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str())); return MIstatus::failure; } lldb::SBError sbError = sbProcess.Destroy(); if (sbError.Fail()) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDBPROCESS_DESTROY), m_cmdData.strMiCmd.c_str(), sbError.GetCString())); return MIstatus::failure; } return MIstatus::success; } //++ // Details: The invoker requires this function. The command prepares a MI Record // Result // for the work carried out in the Execute(). // Type: Overridden. // Args: None. // Return: MIstatus::success - Function succeeded. // MIstatus::failure - Function failed. // Throws: None. //-- bool CMICmdCmdExecAbort::Acknowledge() { m_miResultRecord = CMICmnMIResultRecord( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); return MIstatus::success; } //++ // Details: Required by the CMICmdFactory when registering *this command. The // factory // calls this function to create an instance of *this command. // Type: Static method. // Args: None. // Return: CMICmdBase * - Pointer to a new command. // Throws: None. //-- CMICmdBase *CMICmdCmdExecAbort::CreateSelf() { return new CMICmdCmdExecAbort(); }