diff options
Diffstat (limited to 'tools/lldb-mi/MICmdCmdBreak.cpp')
-rw-r--r-- | tools/lldb-mi/MICmdCmdBreak.cpp | 1026 |
1 files changed, 1026 insertions, 0 deletions
diff --git a/tools/lldb-mi/MICmdCmdBreak.cpp b/tools/lldb-mi/MICmdCmdBreak.cpp new file mode 100644 index 000000000000..f0e9acfe9082 --- /dev/null +++ b/tools/lldb-mi/MICmdCmdBreak.cpp @@ -0,0 +1,1026 @@ +//===-- 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 <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( 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< CMICmdArgValThreadGrp, MIuint >( 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< 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; + 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< 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; + 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< 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.m_lldbTarget.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( 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< 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.m_lldbTarget.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( 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< 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.m_lldbTarget.FindBreakpointByID( static_cast< lldb::break_id_t >( 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< 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( 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< 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( 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< CMICmdArgValListOfN >( 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< CMICmdArgValString * >( *it ); + const CMIUtilString & rPartExpr = pPartExpr->GetValue(); + strExpression += " "; + strExpression += rPartExpr; + + // Next + ++it; + } + strExpression = strExpression.Trim(); + } + } + + return strExpression; +} |