diff options
| author | Deepak Panickal <deepak@codeplay.com> | 2014-05-16 10:51:01 +0000 |
|---|---|---|
| committer | Deepak Panickal <deepak@codeplay.com> | 2014-05-16 10:51:01 +0000 |
| commit | 6f9c46810298dd00dc95d4ffb60faf7d914ab978 (patch) | |
| tree | 7d8abbb2b6cd0aa3dfb8824f318baa432bb9e3c4 /lldb/tools/lldb-mi/MICmdCmdBreak.cpp | |
| parent | d04688d1c6cdffae4623a3a60e2d46f0bd72fe48 (diff) | |
| download | bcm5719-llvm-6f9c46810298dd00dc95d4ffb60faf7d914ab978.tar.gz bcm5719-llvm-6f9c46810298dd00dc95d4ffb60faf7d914ab978.zip | |
Initial commit of LLDB Machine Interface Frontend.
- Tested with Eclipse, likely to work with other GDB/MI compatible GUIs.
- Some but not all MI commands have been implemented. See MIReadme.txt for more info.
- Written from scratch, no GPL code, based on LLDB Public API.
- Built for Linux, Windows and OSX. Tested on Linux and Windows.
- GDB/MI Command Reference, https://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI.html
llvm-svn: 208972
Diffstat (limited to 'lldb/tools/lldb-mi/MICmdCmdBreak.cpp')
| -rw-r--r-- | lldb/tools/lldb-mi/MICmdCmdBreak.cpp | 432 |
1 files changed, 432 insertions, 0 deletions
diff --git a/lldb/tools/lldb-mi/MICmdCmdBreak.cpp b/lldb/tools/lldb-mi/MICmdCmdBreak.cpp new file mode 100644 index 00000000000..63ac8aa6af7 --- /dev/null +++ b/lldb/tools/lldb-mi/MICmdCmdBreak.cpp @@ -0,0 +1,432 @@ +//===-- 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. +// +// 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 "MICmnConfig.h" +#include "MICmdCmdBreak.h" +#include "MICmnMIResultRecord.h" +#include "MICmnMIValueConst.h" +#include "MICmnLLDBDebugger.h" +#include "MICmnLLDBDebugSessionInfo.h" +#include "MICmdArgContext.h" +#include "MICmdArgValFile.h" +#include "MICmdArgValNumber.h" +#include "MICmdArgValString.h" +#include "MICmdArgValThreadGrp.h" +#include "MICmdArgValOptionLong.h" +#include "MICmdArgValOptionShort.h" +#include "MICmdArgValListOfN.h" + +//++ ------------------------------------------------------------------------------------ +// Details: CMICmdCmdBreakInsert constructor. +// Type: Method. +// Args: None. +// Return: None. +// Throws: None. +//-- +CMICmdCmdBreakInsert::CMICmdCmdBreakInsert( void ) +: m_bBrkPtIsTemp( false ) +, m_brkName() +, 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 commmand + 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 )) ); + bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedHWBrkPt, false, false ) ) ); + bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedPendinfBrkPt, false, false ) ) ); + bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedDisableBrkPt, false, false ) ) ); + bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedTracePt, false, false ) ) ); + bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedConditionalBrkPt, false, false ) ) ); + bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedInoreCnt, false, false ) ) ); + bOk = bOk && m_setCmdArgs.Add( *(new CMICmdArgValOptionShort( m_constStrArgNamedRestrictBrkPtToThreadId, false, false ) ) ); + 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 ) ) ); + CMICmdArgContext argCntxt( m_cmdData.strMiCmdOption ); + if( bOk && !m_setCmdArgs.Validate( m_cmdData.strMiCmd, argCntxt ) ) + { + SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_ARGS ), m_cmdData.strMiCmd.c_str(), m_setCmdArgs.GetErrorDescription().c_str() ) ); + return MIstatus::failure; + } + + return bOk; +} + +//++ ------------------------------------------------------------------------------------ +// 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 ) +{ + // Note not all arguments required ATM based on C's version off the code + CMICMDBASE_GETOPTION( pArgTempBrkPt, OptionShort, m_constStrArgNamedTempBrkPt ); + CMICMDBASE_GETOPTION( pArgThreadGroup, OptionLong, m_constStrArgNamedThreadGroup ); + CMICMDBASE_GETOPTION( pArgLocation, String, m_constStrArgNamedLocation ); + + m_bBrkPtIsTemp = pArgTempBrkPt->GetFound(); + m_bHaveArgOptionThreadGrp = pArgThreadGroup->GetFound(); + if( m_bHaveArgOptionThreadGrp ) + { + const CMICmdArgValOptionLong::VecArgObjPtr_t & rVecOptions( pArgThreadGroup->GetExpectedOptions() ); + const CMICmdArgValThreadGrp * pThreadGrp = (rVecOptions.size() > 0) ? static_cast< CMICmdArgValThreadGrp * >( rVecOptions[ 0 ] ) : nullptr; + const MIuint nThreadGrp = (pThreadGrp != nullptr) ? pThreadGrp->GetValue() : 0; + m_strArgOptionThreadGrp = CMIUtilString::Format( "%d", nThreadGrp ); + } + m_brkName = pArgLocation->GetFound() ? pArgLocation->GetValue() : ""; + + // Determine if break on a file line or at a function + BreakPoint_e eBrkPtType = eBreakPoint_NotDefineYet; + const CMIUtilString cColon = ":"; + bool bIsFileLine = false; + bool bIsFileFn = false; + 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 ); + 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( !m_brkPt.IsValid() || !bOk ) + { + SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_INVALID ), m_cmdData.strMiCmd.c_str(), m_brkName.c_str() ) ); + return MIstatus::failure; + } + 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() ); + lldb::SBTarget & rTarget = rSessionInfo.m_lldbTarget; + lldb::SBBreakpointLocation brkPtLoc = m_brkPt.GetLocationAtIndex( 0 ); + lldb::SBAddress brkPtAddr = brkPtLoc.GetAddress(); + lldb::SBSymbolContext symbolCntxt = brkPtAddr.GetSymbolContext( lldb::eSymbolContextEverything ); + const char * pUnkwn = "??"; + lldb::SBModule rModule = symbolCntxt.GetModule(); + const char * pModule = rModule.IsValid() ? rModule.GetFileSpec().GetFilename() : pUnkwn; + const char * pFile = pUnkwn; + const char * pFn = pUnkwn; + const char * pFilePath = pUnkwn; + size_t nLine = 0; + const size_t nAddr = brkPtAddr.GetLoadAddress( rTarget ); + + lldb::SBCompileUnit rCmplUnit = symbolCntxt.GetCompileUnit(); + if( rCmplUnit.IsValid() ) + { + lldb::SBFileSpec rFileSpec = rCmplUnit.GetFileSpec(); + pFile = rFileSpec.GetFilename(); + pFilePath = rFileSpec.GetDirectory(); + lldb::SBFunction rFn = symbolCntxt.GetFunction(); + if( rFn.IsValid() ) + pFn = rFn.GetName(); + lldb::SBLineEntry rLnEntry = symbolCntxt.GetLineEntry(); + if( rLnEntry.GetLine() > 0 ) + nLine = rLnEntry.GetLine(); + } + + // Form MI result record example + // MI print "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\", func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}" + CMICmnMIValueTuple miValueTuple; + if( !CMICmnLLDBDebugSessionInfo::Instance().MIResponseFormBrkPtInfo( m_brkPt.GetID(), // "number=" + "breakpoint", // "type=" + m_bBrkPtIsTemp, // "disp=" + m_brkPt.IsEnabled(), // "enabled=" + nAddr, // "addr=" + pFn, // "func=" + pFile, // "file=" + pFilePath, // "fullname=" + nLine, // "line=" + m_bHaveArgOptionThreadGrp, // + m_strArgOptionThreadGrp, // "thread-groups=" + m_brkPt.GetNumLocations(), // "times=" + m_brkName, // "original-location=" + miValueTuple )) + { + return MIstatus::failure; + } + + const CMICmnMIValueResult miValueResultD( "bkpt", miValueTuple ); + const CMICmnMIResultRecord miRecordResult( m_cmdData.nMiCmdNumber, CMICmnMIResultRecord::eResultClass_Done, miValueResultD ); + m_miResultRecord = miRecordResult; + + return MIstatus::success; +} + +//++ ------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this commmand. 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 commmand + 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 ) ) ); + CMICmdArgContext argCntxt( m_cmdData.strMiCmdOption ); + if( bOk && !m_setCmdArgs.Validate( m_cmdData.strMiCmd, argCntxt ) ) + { + SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_ARGS ), m_cmdData.strMiCmd.c_str(), m_setCmdArgs.GetErrorDescription().c_str() ) ); + return MIstatus::failure; + } + + return bOk; +} + +//++ ------------------------------------------------------------------------------------ +// 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 ) ) + { + const CMIUtilString errMsg( CMIUtilString::Format( MIRSRC( IDS_CMD_ARGS_ERR_N_OPTIONS_REQUIRED ), 1 ) ); + SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_INVALID ), m_cmdData.strMiCmd.c_str(), errMsg.c_str() ) ); + return MIstatus::failure; + } + + const CMIUtilString strBrkNum( CMIUtilString::Format( "%d", nBrk ) ); + CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); + const bool bBrkPt = rSessionInfo.m_lldbTarget.BreakpointDelete( static_cast< lldb::break_id_t >( nBrk ) ); + if( !bBrkPt ) + { + 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.nMiCmdNumber, CMICmnMIResultRecord::eResultClass_Done ); + m_miResultRecord = miRecordResult; + + return MIstatus::success; +} + +//++ ------------------------------------------------------------------------------------ +// Details: Required by the CMICmdFactory when registering *this commmand. 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(); +} |

