//===-- 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 "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() : 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)); 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); 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; 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; CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBTarget sbTarget = rSessionInfo.GetTarget(); 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 CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", m_nBrkPtId)); const CMICmnMIValueResult miValueResult("number", miValueConst); CMICmnMIValueTuple miValueTuple(miValueResult); const CMICmnMIValueConst miValueConst2("n"); const CMICmnMIValueResult miValueResult2("enabled", miValueConst2); miValueTuple.Add(miValueResult2); const CMICmnMIValueResult miValueResult3("bkpt", miValueTuple); const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult3); bool 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() { 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(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() { 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); miValueTuple.Add(miValueResult2); const CMICmnMIValueResult miValueResult3("bkpt", miValueTuple); const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult3); bool 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() { 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; }