//===-- MICmdCmdBreak.cpp ---------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // Overview: CMICmdCmdBreakInsert implementation. // CMICmdCmdBreakDelete implementation. // CMICmdCmdBreakDisable implementation. // CMICmdCmdBreakEnable implementation. // CMICmdCmdBreakAfter implementation. // CMICmdCmdBreakCondition implementation. // Third Party Headers: #include "lldb/API/SBBreakpointLocation.h" // In-house headers: #include "MICmdArgValFile.h" #include "MICmdArgValListOfN.h" #include "MICmdArgValNumber.h" #include "MICmdArgValOptionLong.h" #include "MICmdArgValOptionShort.h" #include "MICmdArgValString.h" #include "MICmdArgValThreadGrp.h" #include "MICmdCmdBreak.h" #include "MICmnLLDBDebugSessionInfo.h" #include "MICmnLLDBDebugger.h" #include "MICmnMIOutOfBandRecord.h" #include "MICmnMIResultRecord.h" #include "MICmnMIValueConst.h" #include "MICmnStreamStdout.h" //++ //------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakInsert constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdBreakInsert::CMICmdCmdBreakInsert() : m_bBrkPtIsTemp(false), m_bBrkPtIsPending(false), m_nBrkPtIgnoreCount(0), m_bBrkPtEnabled(false), m_bBrkPtCondition(false), m_bBrkPtThreadId(false), m_nBrkPtThreadId(0), m_constStrArgNamedTempBrkPt("t"), m_constStrArgNamedHWBrkPt("h"), m_constStrArgNamedPendinfBrkPt("f"), m_constStrArgNamedDisableBrkPt("d"), m_constStrArgNamedTracePt("a"), m_constStrArgNamedConditionalBrkPt("c"), m_constStrArgNamedInoreCnt("i"), m_constStrArgNamedRestrictBrkPtToThreadId("p"), m_constStrArgNamedLocation("location") { // Command factory matches this name with that received from the stdin stream m_strMiCmd = "break-insert"; // Required by the CMICmdFactory when registering *this command m_pSelfCreatorFn = &CMICmdCmdBreakInsert::CreateSelf; } //++ //------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakInsert destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdBreakInsert::~CMICmdCmdBreakInsert() {} //++ //------------------------------------------------------------------------------------ // 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 CMICmdCmdBreakInsert::ParseArgs() { m_setCmdArgs.Add( new CMICmdArgValOptionShort(m_constStrArgNamedTempBrkPt, false, true)); // Not implemented m_setCmdArgs.Add(new CMICmdArgValOptionShort( // m_constStrArgNamedHWBrkPt, false, false)); m_setCmdArgs.Add(new CMICmdArgValOptionShort( m_constStrArgNamedPendinfBrkPt, false, true, CMICmdArgValListBase::eArgValType_StringQuotedNumberPath, 1)); m_setCmdArgs.Add(new CMICmdArgValOptionShort(m_constStrArgNamedDisableBrkPt, false, false)); // Not implemented m_setCmdArgs.Add(new CMICmdArgValOptionShort( // m_constStrArgNamedTracePt, false, false)); m_setCmdArgs.Add(new CMICmdArgValOptionShort( m_constStrArgNamedConditionalBrkPt, false, true, CMICmdArgValListBase::eArgValType_StringQuoted, 1)); m_setCmdArgs.Add( new CMICmdArgValOptionShort(m_constStrArgNamedInoreCnt, false, true, CMICmdArgValListBase::eArgValType_Number, 1)); m_setCmdArgs.Add(new CMICmdArgValOptionShort( m_constStrArgNamedRestrictBrkPtToThreadId, false, true, CMICmdArgValListBase::eArgValType_Number, 1)); m_setCmdArgs.Add(new CMICmdArgValString(m_constStrArgNamedLocation, false, true, false, false, true)); return ParseValidateCmdOptions(); } //++ //------------------------------------------------------------------------------------ // Helper function for CMICmdCmdBreakInsert::Execute(). // // Given a string, return the position of the ':' separator in 'file:func' // or 'file:line', if any. If not found, return npos. For example, return // 5 for 'foo.c:std::string'. //-- static size_t findFileSeparatorPos(const std::string &x) { // Full paths in windows can have ':' after a drive letter, so we // search backwards, taking care to skip C++ namespace tokens '::'. size_t n = x.rfind(':'); while (n != std::string::npos && n > 1 && x[n - 1] == ':') { n = x.rfind(':', n - 2); } return n; } //++ //------------------------------------------------------------------------------------ // 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 CMICmdCmdBreakInsert::Execute() { CMICMDBASE_GETOPTION(pArgTempBrkPt, OptionShort, m_constStrArgNamedTempBrkPt); CMICMDBASE_GETOPTION(pArgThreadGroup, OptionLong, m_constStrArgThreadGroup); CMICMDBASE_GETOPTION(pArgLocation, String, m_constStrArgNamedLocation); CMICMDBASE_GETOPTION(pArgIgnoreCnt, OptionShort, m_constStrArgNamedInoreCnt); CMICMDBASE_GETOPTION(pArgPendingBrkPt, OptionShort, m_constStrArgNamedPendinfBrkPt); CMICMDBASE_GETOPTION(pArgDisableBrkPt, OptionShort, m_constStrArgNamedDisableBrkPt); CMICMDBASE_GETOPTION(pArgConditionalBrkPt, OptionShort, m_constStrArgNamedConditionalBrkPt); CMICMDBASE_GETOPTION(pArgRestrictBrkPtToThreadId, OptionShort, m_constStrArgNamedRestrictBrkPtToThreadId); // Ask LLDB for the target to check if we have valid or dummy one. CMICmnLLDBDebugSessionInfo &rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBTarget sbTarget = rSessionInfo.GetTarget(); m_bBrkPtEnabled = !pArgDisableBrkPt->GetFound(); m_bBrkPtIsTemp = pArgTempBrkPt->GetFound(); m_bHaveArgOptionThreadGrp = pArgThreadGroup->GetFound(); if (m_bHaveArgOptionThreadGrp) { MIuint nThreadGrp = 0; pArgThreadGroup->GetExpectedOption( nThreadGrp); m_strArgOptionThreadGrp = CMIUtilString::Format("i%d", nThreadGrp); } if (sbTarget == rSessionInfo.GetDebugger().GetDummyTarget()) m_bBrkPtIsPending = true; else { m_bBrkPtIsPending = pArgPendingBrkPt->GetFound(); if (!m_bBrkPtIsPending) { CMIUtilString pending; if (m_rLLDBDebugSessionInfo.SharedDataRetrieve("breakpoint.pending", pending)) { m_bBrkPtIsPending = pending == "on"; } } } if (pArgLocation->GetFound()) m_brkName = pArgLocation->GetValue(); else if (m_bBrkPtIsPending) { pArgPendingBrkPt->GetExpectedOption( m_brkName); } if (pArgIgnoreCnt->GetFound()) { pArgIgnoreCnt->GetExpectedOption( m_nBrkPtIgnoreCount); } m_bBrkPtCondition = pArgConditionalBrkPt->GetFound(); if (m_bBrkPtCondition) { pArgConditionalBrkPt->GetExpectedOption( m_brkPtCondition); } m_bBrkPtThreadId = pArgRestrictBrkPtToThreadId->GetFound(); if (m_bBrkPtCondition) { pArgRestrictBrkPtToThreadId->GetExpectedOption( m_nBrkPtThreadId); } // Determine if break on a file line or at a function BreakPoint_e eBrkPtType = eBreakPoint_NotDefineYet; CMIUtilString fileName; MIuint nFileLine = 0; CMIUtilString strFileFn; CMIUtilString rStrLineOrFn; // Is the string in the form 'file:func' or 'file:line'? // If so, find the position of the ':' separator. const size_t nPosColon = findFileSeparatorPos(m_brkName); if (nPosColon != std::string::npos) { // Extract file name and line number from it fileName = m_brkName.substr(0, nPosColon); rStrLineOrFn = m_brkName.substr(nPosColon + 1, m_brkName.size() - nPosColon - 1); if (rStrLineOrFn.empty()) eBrkPtType = eBreakPoint_ByName; else { MIint64 nValue = 0; if (rStrLineOrFn.ExtractNumber(nValue)) { nFileLine = static_cast(nValue); eBrkPtType = eBreakPoint_ByFileLine; } else { strFileFn = rStrLineOrFn; eBrkPtType = eBreakPoint_ByFileFn; } } } // Determine if break defined as an address lldb::addr_t nAddress = 0; if (eBrkPtType == eBreakPoint_NotDefineYet) { MIint64 nValue = 0; if (m_brkName.ExtractNumber(nValue)) { nAddress = static_cast(nValue); eBrkPtType = eBreakPoint_ByAddress; } } // Break defined as an function if (eBrkPtType == eBreakPoint_NotDefineYet) { eBrkPtType = eBreakPoint_ByName; } // Ask LLDB to create a breakpoint bool bOk = MIstatus::success; switch (eBrkPtType) { case eBreakPoint_ByAddress: m_brkPt = sbTarget.BreakpointCreateByAddress(nAddress); break; case eBreakPoint_ByFileFn: { lldb::SBFileSpecList module; // search in all modules lldb::SBFileSpecList compUnit; compUnit.Append(lldb::SBFileSpec(fileName.c_str())); m_brkPt = sbTarget.BreakpointCreateByName(strFileFn.c_str(), module, compUnit); break; } case eBreakPoint_ByFileLine: m_brkPt = sbTarget.BreakpointCreateByLocation(fileName.c_str(), nFileLine); break; case eBreakPoint_ByName: m_brkPt = sbTarget.BreakpointCreateByName(m_brkName.c_str(), nullptr); break; case eBreakPoint_count: case eBreakPoint_NotDefineYet: case eBreakPoint_Invalid: bOk = MIstatus::failure; break; } if (bOk) { if (!m_bBrkPtIsPending && (m_brkPt.GetNumLocations() == 0)) { sbTarget.BreakpointDelete(m_brkPt.GetID()); SetError( CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_LOCATION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_brkName.c_str())); return MIstatus::failure; } m_brkPt.SetEnabled(m_bBrkPtEnabled); m_brkPt.SetIgnoreCount(m_nBrkPtIgnoreCount); if (m_bBrkPtCondition) m_brkPt.SetCondition(m_brkPtCondition.c_str()); if (m_bBrkPtThreadId) m_brkPt.SetThreadID(m_nBrkPtThreadId); } // CODETAG_LLDB_BREAKPOINT_CREATION // This is in the main thread // Record break point information to be by LLDB event handler function CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; if (!rSessionInfo.GetBrkPtInfo(m_brkPt, sBrkPtInfo)) return MIstatus::failure; sBrkPtInfo.m_id = m_brkPt.GetID(); sBrkPtInfo.m_bDisp = m_bBrkPtIsTemp; sBrkPtInfo.m_bEnabled = m_bBrkPtEnabled; sBrkPtInfo.m_bHaveArgOptionThreadGrp = m_bHaveArgOptionThreadGrp; sBrkPtInfo.m_strOptThrdGrp = m_strArgOptionThreadGrp; sBrkPtInfo.m_nTimes = m_brkPt.GetHitCount(); sBrkPtInfo.m_strOrigLoc = m_brkName; sBrkPtInfo.m_nIgnore = m_nBrkPtIgnoreCount; sBrkPtInfo.m_bPending = m_bBrkPtIsPending; sBrkPtInfo.m_bCondition = m_bBrkPtCondition; sBrkPtInfo.m_strCondition = m_brkPtCondition; sBrkPtInfo.m_bBrkPtThreadId = m_bBrkPtThreadId; sBrkPtInfo.m_nBrkPtThreadId = m_nBrkPtThreadId; bOk = bOk && rSessionInfo.RecordBrkPtInfo(m_brkPt.GetID(), sBrkPtInfo); if (!bOk) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), m_brkName.c_str())); return MIstatus::failure; } // CODETAG_LLDB_BRKPT_ID_MAX if (m_brkPt.GetID() > (lldb::break_id_t)rSessionInfo.m_nBrkPointCntMax) { SetError(CMIUtilString::Format( MIRSRC(IDS_CMD_ERR_BRKPT_CNT_EXCEEDED), m_cmdData.strMiCmd.c_str(), rSessionInfo.m_nBrkPointCntMax, m_brkName.c_str())); 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 - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdBreakInsert::Acknowledge() { // Get breakpoint information CMICmnLLDBDebugSessionInfo &rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance()); CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; if (!rSessionInfo.RecordBrkPtInfoGet(m_brkPt.GetID(), sBrkPtInfo)) return MIstatus::failure; // MI print // "^done,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016" // PRIx64 // "\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",thread-groups=[\"%s\"],times=\"%d\",original-location=\"%s\"}" CMICmnMIValueTuple miValueTuple; if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple)) return MIstatus::failure; const CMICmnMIValueResult miValueResultD("bkpt", miValueTuple); const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResultD); m_miResultRecord = miRecordResult; 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 *CMICmdCmdBreakInsert::CreateSelf() { return new CMICmdCmdBreakInsert(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //++ //------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakDelete constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdBreakDelete::CMICmdCmdBreakDelete() : m_constStrArgNamedBrkPt("breakpoint") { // Command factory matches this name with that received from the stdin stream m_strMiCmd = "break-delete"; // Required by the CMICmdFactory when registering *this command m_pSelfCreatorFn = &CMICmdCmdBreakDelete::CreateSelf; } //++ //------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakDelete destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdBreakDelete::~CMICmdCmdBreakDelete() {} //++ //------------------------------------------------------------------------------------ // 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 CMICmdCmdBreakDelete::ParseArgs() { m_setCmdArgs.Add( new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number)); 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 CMICmdCmdBreakDelete::Execute() { CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt); // ATM we only handle one break point ID MIuint64 nBrk = UINT64_MAX; if (!pArgBrkPt->GetExpectedOption(nBrk)) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgNamedBrkPt.c_str())); return MIstatus::failure; } CMICmnLLDBDebugSessionInfo &rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance()); const bool bBrkPt = rSessionInfo.GetTarget().BreakpointDelete( static_cast(nBrk)); if (!bBrkPt) { const CMIUtilString strBrkNum(CMIUtilString::Format("%d", nBrk)); SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), strBrkNum.c_str())); 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 - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdBreakDelete::Acknowledge() { const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); m_miResultRecord = miRecordResult; 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 *CMICmdCmdBreakDelete::CreateSelf() { return new CMICmdCmdBreakDelete(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //++ //------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakDisable constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdBreakDisable::CMICmdCmdBreakDisable() : m_constStrArgNamedBrkPt("breakpoint"), m_bBrkPtDisabledOk(false), m_nBrkPtId(0) { // Command factory matches this name with that received from the stdin stream m_strMiCmd = "break-disable"; // Required by the CMICmdFactory when registering *this command m_pSelfCreatorFn = &CMICmdCmdBreakDisable::CreateSelf; } //++ //------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakDisable destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdBreakDisable::~CMICmdCmdBreakDisable() {} //++ //------------------------------------------------------------------------------------ // 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 CMICmdCmdBreakDisable::ParseArgs() { m_setCmdArgs.Add( new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number)); 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 CMICmdCmdBreakDisable::Execute() { CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt); // ATM we only handle one break point ID MIuint64 nBrk = UINT64_MAX; if (!pArgBrkPt->GetExpectedOption(nBrk)) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgNamedBrkPt.c_str())); return MIstatus::failure; } CMICmnLLDBDebugSessionInfo &rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID( static_cast(nBrk)); if (brkPt.IsValid()) { m_bBrkPtDisabledOk = true; brkPt.SetEnabled(false); m_nBrkPtId = nBrk; } 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 - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdBreakDisable::Acknowledge() { if (m_bBrkPtDisabledOk) { const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); m_miResultRecord = miRecordResult; return MIstatus::success; } const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId)); const CMICmnMIValueConst miValueConst(CMIUtilString::Format( MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), strBrkPtId.c_str())); const CMICmnMIValueResult miValueResult("msg", miValueConst); const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); m_miResultRecord = miRecordResult; 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 *CMICmdCmdBreakDisable::CreateSelf() { return new CMICmdCmdBreakDisable(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //++ //------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakEnable constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdBreakEnable::CMICmdCmdBreakEnable() : m_constStrArgNamedBrkPt("breakpoint"), m_bBrkPtEnabledOk(false), m_nBrkPtId(0) { // Command factory matches this name with that received from the stdin stream m_strMiCmd = "break-enable"; // Required by the CMICmdFactory when registering *this command m_pSelfCreatorFn = &CMICmdCmdBreakEnable::CreateSelf; } //++ //------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakEnable destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdBreakEnable::~CMICmdCmdBreakEnable() {} //++ //------------------------------------------------------------------------------------ // 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 CMICmdCmdBreakEnable::ParseArgs() { m_setCmdArgs.Add( new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number)); 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 CMICmdCmdBreakEnable::Execute() { CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt); // ATM we only handle one break point ID MIuint64 nBrk = UINT64_MAX; if (!pArgBrkPt->GetExpectedOption(nBrk)) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgNamedBrkPt.c_str())); return MIstatus::failure; } CMICmnLLDBDebugSessionInfo &rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID( static_cast(nBrk)); if (brkPt.IsValid()) { m_bBrkPtEnabledOk = true; brkPt.SetEnabled(true); m_nBrkPtId = nBrk; } 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 - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdBreakEnable::Acknowledge() { if (m_bBrkPtEnabledOk) { const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); m_miResultRecord = miRecordResult; return MIstatus::success; } const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId)); const CMICmnMIValueConst miValueConst(CMIUtilString::Format( MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), strBrkPtId.c_str())); const CMICmnMIValueResult miValueResult("msg", miValueConst); const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); m_miResultRecord = miRecordResult; 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 *CMICmdCmdBreakEnable::CreateSelf() { return new CMICmdCmdBreakEnable(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //++ //------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakAfter constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdBreakAfter::CMICmdCmdBreakAfter() : m_constStrArgNamedNumber("number"), m_constStrArgNamedCount("count"), m_nBrkPtId(0), m_nBrkPtCount(0) { // Command factory matches this name with that received from the stdin stream m_strMiCmd = "break-after"; // Required by the CMICmdFactory when registering *this command m_pSelfCreatorFn = &CMICmdCmdBreakAfter::CreateSelf; } //++ //------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakAfter destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdBreakAfter::~CMICmdCmdBreakAfter() {} //++ //------------------------------------------------------------------------------------ // 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 CMICmdCmdBreakAfter::ParseArgs() { m_setCmdArgs.Add( new CMICmdArgValNumber(m_constStrArgNamedNumber, true, true)); m_setCmdArgs.Add(new CMICmdArgValNumber(m_constStrArgNamedCount, true, true)); 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 CMICmdCmdBreakAfter::Execute() { CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNamedNumber); CMICMDBASE_GETOPTION(pArgCount, Number, m_constStrArgNamedCount); m_nBrkPtId = pArgNumber->GetValue(); m_nBrkPtCount = pArgCount->GetValue(); CMICmnLLDBDebugSessionInfo &rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID( static_cast(m_nBrkPtId)); if (brkPt.IsValid()) { brkPt.SetIgnoreCount(m_nBrkPtCount); CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; if (!rSessionInfo.RecordBrkPtInfoGet(m_nBrkPtId, sBrkPtInfo)) { SetError( CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_nBrkPtId)); return MIstatus::failure; } sBrkPtInfo.m_nIgnore = m_nBrkPtCount; rSessionInfo.RecordBrkPtInfo(m_nBrkPtId, sBrkPtInfo); } else { const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId)); SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), strBrkPtId.c_str())); 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 - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdBreakAfter::Acknowledge() { const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); m_miResultRecord = miRecordResult; 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 *CMICmdCmdBreakAfter::CreateSelf() { return new CMICmdCmdBreakAfter(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //++ //------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakCondition constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdBreakCondition::CMICmdCmdBreakCondition() : m_constStrArgNamedNumber("number"), m_constStrArgNamedExpr("expr"), m_constStrArgNamedExprNoQuotes( "expression not surround by quotes") // Not specified in MI spec, we // need to handle expressions not // surrounded by quotes , m_nBrkPtId(0) { // Command factory matches this name with that received from the stdin stream m_strMiCmd = "break-condition"; // Required by the CMICmdFactory when registering *this command m_pSelfCreatorFn = &CMICmdCmdBreakCondition::CreateSelf; } //++ //------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakCondition destructor. // Type: Overrideable. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdBreakCondition::~CMICmdCmdBreakCondition() {} //++ //------------------------------------------------------------------------------------ // 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 CMICmdCmdBreakCondition::ParseArgs() { m_setCmdArgs.Add( new CMICmdArgValNumber(m_constStrArgNamedNumber, true, true)); m_setCmdArgs.Add( new CMICmdArgValString(m_constStrArgNamedExpr, true, true, true, true)); m_setCmdArgs.Add(new CMICmdArgValListOfN( m_constStrArgNamedExprNoQuotes, false, false, CMICmdArgValListBase::eArgValType_StringQuotedNumber)); 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 CMICmdCmdBreakCondition::Execute() { CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNamedNumber); CMICMDBASE_GETOPTION(pArgExpr, String, m_constStrArgNamedExpr); m_nBrkPtId = pArgNumber->GetValue(); m_strBrkPtExpr = pArgExpr->GetValue(); m_strBrkPtExpr += GetRestOfExpressionNotSurroundedInQuotes(); CMICmnLLDBDebugSessionInfo &rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID( static_cast(m_nBrkPtId)); if (brkPt.IsValid()) { brkPt.SetCondition(m_strBrkPtExpr.c_str()); CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; if (!rSessionInfo.RecordBrkPtInfoGet(m_nBrkPtId, sBrkPtInfo)) { SetError( CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_nBrkPtId)); return MIstatus::failure; } sBrkPtInfo.m_strCondition = m_strBrkPtExpr; rSessionInfo.RecordBrkPtInfo(m_nBrkPtId, sBrkPtInfo); } else { const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId)); SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), strBrkPtId.c_str())); 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 - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdBreakCondition::Acknowledge() { const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); m_miResultRecord = miRecordResult; 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 *CMICmdCmdBreakCondition::CreateSelf() { return new CMICmdCmdBreakCondition(); } //++ //------------------------------------------------------------------------------------ // Details: A breakpoint expression can be passed to *this command as: // a single string i.e. '2' -> ok. // a quoted string i.e. "a > 100" -> ok // a non quoted string i.e. 'a > 100' -> not ok // CMICmdArgValString only extracts the first space separated string, // the "a". // This function using the optional argument type CMICmdArgValListOfN // collects // the rest of the expression so that is may be added to the 'a' part // to form a // complete expression string i.e. "a > 100". // If the expression value was guaranteed to be surrounded by quotes // them this // function would not be necessary. // Type: Method. // Args: None. // Return: CMIUtilString - Rest of the breakpoint expression. // Throws: None. //-- CMIUtilString CMICmdCmdBreakCondition::GetRestOfExpressionNotSurroundedInQuotes() { CMIUtilString strExpression; CMICmdArgValListOfN *pArgExprNoQuotes = CMICmdBase::GetOption( m_constStrArgNamedExprNoQuotes); if (pArgExprNoQuotes != nullptr) { const CMICmdArgValListBase::VecArgObjPtr_t &rVecExprParts( pArgExprNoQuotes->GetExpectedOptions()); if (!rVecExprParts.empty()) { CMICmdArgValListBase::VecArgObjPtr_t::const_iterator it = rVecExprParts.begin(); while (it != rVecExprParts.end()) { const CMICmdArgValString *pPartExpr = static_cast(*it); const CMIUtilString &rPartExpr = pPartExpr->GetValue(); strExpression += " "; strExpression += rPartExpr; // Next ++it; } strExpression = strExpression.Trim(); } } return strExpression; }