//===-- MICmdCmdBreak.cpp ---------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// //++ // File: MICmdCmdBreak.cpp // // Overview: CMICmdCmdBreakInsert implementation. // CMICmdCmdBreakDelete implementation. // CMICmdCmdBreakDisable implementation. // CMICmdCmdBreakEnable implementation. // CMICmdCmdBreakAfter implementation. // CMICmdCmdBreakCondition implementation. // // Environment: Compilers: Visual C++ 12. // gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 // Libraries: See MIReadmetxt. // // Copyright: None. //-- // Third Party Headers: #include // In-house headers: #include "MICmdCmdBreak.h" #include "MICmnMIResultRecord.h" #include "MICmnMIValueConst.h" #include "MICmnMIOutOfBandRecord.h" #include "MICmnLLDBDebugger.h" #include "MICmnLLDBDebugSessionInfo.h" #include "MICmdArgValFile.h" #include "MICmdArgValNumber.h" #include "MICmdArgValString.h" #include "MICmdArgValThreadGrp.h" #include "MICmdArgValOptionLong.h" #include "MICmdArgValOptionShort.h" #include "MICmdArgValListOfN.h" #include "MICmnStreamStdout.h" //++ ------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakInsert constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdBreakInsert::CMICmdCmdBreakInsert(void) : 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") , m_constStrArgNamedThreadGroup("thread-group") { // 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(void) { } //++ ------------------------------------------------------------------------------------ // 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(void) { bool bOk = m_setCmdArgs.Add(*(new CMICmdArgValOptionShort(m_constStrArgNamedTempBrkPt, false, true))); // Not implemented bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedHWBrkPt, false, false ) ) ); bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValOptionShort(m_constStrArgNamedPendinfBrkPt, false, true, CMICmdArgValListBase::eArgValType_StringQuotedNumberPath, 1))); bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValOptionShort(m_constStrArgNamedDisableBrkPt, false, false))); // Not implemented bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedTracePt, false, false ) ) ); bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValOptionShort(m_constStrArgNamedConditionalBrkPt, false, true, CMICmdArgValListBase::eArgValType_StringQuoted, 1))); bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort(m_constStrArgNamedInoreCnt, false, true, CMICmdArgValListBase::eArgValType_Number, 1))); bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValOptionShort(m_constStrArgNamedRestrictBrkPtToThreadId, false, true, CMICmdArgValListBase::eArgValType_Number, 1))); bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgNamedLocation, false, true))); bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionLong(m_constStrArgNamedThreadGroup, false, true, CMICmdArgValListBase::eArgValType_ThreadGrp, 1))); return (bOk && 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 CMICmdCmdBreakInsert::Execute(void) { CMICMDBASE_GETOPTION(pArgTempBrkPt, OptionShort, m_constStrArgNamedTempBrkPt); CMICMDBASE_GETOPTION(pArgThreadGroup, OptionLong, m_constStrArgNamedThreadGroup); 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); 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); } m_bBrkPtIsPending = pArgPendingBrkPt->GetFound(); 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; const CMIUtilString cColon = ":"; CMIUtilString fileName; MIuint nFileLine = 0; CMIUtilString strFileFn; const MIint nPosColon = m_brkName.find(cColon); if (nPosColon != (MIint)std::string::npos) { CMIUtilString::VecString_t vecFileAndLocation; const MIuint nSplits = m_brkName.Split(cColon, vecFileAndLocation); MIunused(nSplits); if (vecFileAndLocation.size() != 2) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_LOCATION_FORMAT), m_cmdData.strMiCmd.c_str(), m_brkName.c_str())); return MIstatus::failure; } fileName = vecFileAndLocation.at(0); const CMIUtilString &rStrLineOrFn(vecFileAndLocation.at(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; CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBTarget &rTarget = rSessionInfo.m_lldbTarget; switch (eBrkPtType) { case eBreakPoint_ByAddress: m_brkPt = rTarget.BreakpointCreateByAddress(nAddress); break; case eBreakPoint_ByFileFn: m_brkPt = rTarget.BreakpointCreateByName(strFileFn.c_str(), fileName.c_str()); break; case eBreakPoint_ByFileLine: m_brkPt = rTarget.BreakpointCreateByLocation(fileName.c_str(), nFileLine); break; case eBreakPoint_ByName: m_brkPt = rTarget.BreakpointCreateByName(m_brkName.c_str(), rTarget.GetExecutable().GetFilename()); break; case eBreakPoint_count: case eBreakPoint_NotDefineYet: case eBreakPoint_Invalid: bOk = MIstatus::failure; break; } if (bOk) { 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); if (!m_brkPt.IsValid()) m_bBrkPtIsPending = pArgPendingBrkPt->GetFound(); } // CODETAG_LLDB_BREAKPOINT_CREATION // This is in the main thread // Record break point information to be by LLDB event handler function CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; 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_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(void) { // Get breakpoint information CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; if (!rSessionInfo.GetBrkPtInfo(m_brkPt, sBrkPtInfo)) { return MIstatus::failure; } // CODETAG_LLDB_BREAKPOINT_CREATION // Add more breakpoint information or overwrite existing information 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.GetNumLocations(); 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; // MI print // "^done,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\",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(void) { return new CMICmdCmdBreakInsert(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakDelete constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdBreakDelete::CMICmdCmdBreakDelete(void) : m_constStrArgNamedBrkPt("breakpoint") , m_constStrArgNamedThreadGrp("thread-group") { // 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(void) { } //++ ------------------------------------------------------------------------------------ // 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(void) { bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong(m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1))); bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number))); return (bOk && 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(void) { 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.m_lldbTarget.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(void) { 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(void) { return new CMICmdCmdBreakDelete(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakDisable constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdBreakDisable::CMICmdCmdBreakDisable(void) : m_constStrArgNamedThreadGrp("thread-group") , 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(void) { } //++ ------------------------------------------------------------------------------------ // 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(void) { bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong(m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1))); bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number))); return (bOk && 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(void) { 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.m_lldbTarget.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(void) { if (m_bBrkPtDisabledOk) { const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", m_nBrkPtId)); const CMICmnMIValueResult miValueResult("number", miValueConst); CMICmnMIValueTuple miValueTuple(miValueResult); const CMICmnMIValueConst miValueConst2("n"); const CMICmnMIValueResult miValueResult2("enabled", miValueConst2); bool bOk = miValueTuple.Add(miValueResult2); const CMICmnMIValueResult miValueResult3("bkpt", miValueTuple); const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult3); bOk = bOk && CMICmnStreamStdout::TextToStdout(miOutOfBandRecord.GetString()); const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); m_miResultRecord = miRecordResult; return bOk; } 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(void) { return new CMICmdCmdBreakDisable(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakEnable constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdBreakEnable::CMICmdCmdBreakEnable(void) : m_constStrArgNamedThreadGrp("thread-group") , 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(void) { } //++ ------------------------------------------------------------------------------------ // 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(void) { bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong(m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1))); bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValListOfN(m_constStrArgNamedBrkPt, true, true, CMICmdArgValListBase::eArgValType_Number))); return (bOk && 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(void) { 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.m_lldbTarget.FindBreakpointByID(static_cast(nBrk)); if (brkPt.IsValid()) { m_bBrkPtEnabledOk = 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 CMICmdCmdBreakEnable::Acknowledge(void) { if (m_bBrkPtEnabledOk) { const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", m_nBrkPtId)); const CMICmnMIValueResult miValueResult("number", miValueConst); CMICmnMIValueTuple miValueTuple(miValueResult); const CMICmnMIValueConst miValueConst2("y"); const CMICmnMIValueResult miValueResult2("enabled", miValueConst2); bool bOk = miValueTuple.Add(miValueResult2); const CMICmnMIValueResult miValueResult3("bkpt", miValueTuple); const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult3); bOk = bOk && CMICmnStreamStdout::TextToStdout(miOutOfBandRecord.GetString()); const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done); m_miResultRecord = miRecordResult; return bOk; } 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(void) { return new CMICmdCmdBreakEnable(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakAfter constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdBreakAfter::CMICmdCmdBreakAfter(void) : m_constStrArgNamedThreadGrp("thread-group") , 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(void) { } //++ ------------------------------------------------------------------------------------ // 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(void) { bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong(m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1))); bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNamedNumber, true, true))); bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNamedCount, true, true))); return (bOk && 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(void) { 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.m_lldbTarget.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(void) { 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(void) { return new CMICmdCmdBreakAfter(); } //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------- //++ ------------------------------------------------------------------------------------ // Details: CMICmdCmdBreakCondition constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmdCmdBreakCondition::CMICmdCmdBreakCondition(void) : m_constStrArgNamedThreadGrp("thread-group") , 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(void) { } //++ ------------------------------------------------------------------------------------ // 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(void) { bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValOptionLong(m_constStrArgNamedThreadGrp, false, false, CMICmdArgValListBase::eArgValType_ThreadGrp, 1))); bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValNumber(m_constStrArgNamedNumber, true, true))); bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValString(m_constStrArgNamedExpr, true, true, true, true))); bOk = bOk && m_setCmdArgs.Add(*(new CMICmdArgValListOfN(m_constStrArgNamedExprNoQuotes, true, false, CMICmdArgValListBase::eArgValType_StringQuotedNumber))); return (bOk && 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(void) { 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.m_lldbTarget.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(void) { 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(void) { 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 seperated 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(void) { CMIUtilString strExpression; CMICmdArgValListOfN *pArgExprNoQuotes = CMICmdBase::GetOption(m_constStrArgNamedExprNoQuotes); if (pArgExprNoQuotes != nullptr) { CMIUtilString strExpression; 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; }