| //===-- 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<CMICmdArgValThreadGrp, MIuint>( |
| nThreadGrp); |
| m_strArgOptionThreadGrp = CMIUtilString::Format("i%d", nThreadGrp); |
| } |
| |
| if (sbTarget == rSessionInfo.GetDebugger().GetDummyTarget()) |
| m_bBrkPtIsPending = true; |
| else |
| m_bBrkPtIsPending = pArgPendingBrkPt->GetFound(); |
| |
| if (pArgLocation->GetFound()) |
| m_brkName = pArgLocation->GetValue(); |
| else if (m_bBrkPtIsPending) { |
| pArgPendingBrkPt->GetExpectedOption<CMICmdArgValString, CMIUtilString>( |
| m_brkName); |
| } |
| if (pArgIgnoreCnt->GetFound()) { |
| pArgIgnoreCnt->GetExpectedOption<CMICmdArgValNumber, MIuint>( |
| m_nBrkPtIgnoreCount); |
| } |
| m_bBrkPtCondition = pArgConditionalBrkPt->GetFound(); |
| if (m_bBrkPtCondition) { |
| pArgConditionalBrkPt->GetExpectedOption<CMICmdArgValString, CMIUtilString>( |
| m_brkPtCondition); |
| } |
| m_bBrkPtThreadId = pArgRestrictBrkPtToThreadId->GetFound(); |
| if (m_bBrkPtCondition) { |
| pArgRestrictBrkPtToThreadId->GetExpectedOption<CMICmdArgValNumber, MIuint>( |
| 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<MIuint>(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<lldb::addr_t>(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<CMICmdArgValNumber, MIuint64>(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<lldb::break_id_t>(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<CMICmdArgValNumber, MIuint64>(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<lldb::break_id_t>(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<CMICmdArgValNumber, MIuint64>(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<lldb::break_id_t>(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<lldb::break_id_t>(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<lldb::break_id_t>(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<CMICmdArgValListOfN>( |
| 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<CMICmdArgValString *>(*it); |
| const CMIUtilString &rPartExpr = pPartExpr->GetValue(); |
| strExpression += " "; |
| strExpression += rPartExpr; |
| |
| // Next |
| ++it; |
| } |
| strExpression = strExpression.Trim(); |
| } |
| } |
| |
| return strExpression; |
| } |