| //===-- MICmdCmdThread.cpp --------------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| //++ |
| // File: MICmdCmdThread.cpp |
| // |
| // Overview: CMICmdCmdThreadInfo 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> |
| #include <lldb/API/SBThread.h> |
| |
| // In-house headers: |
| #include "MICmnConfig.h" |
| #include "MICmdCmdThread.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: CMICmdCmdThreadInfo constructor. |
| // Type: Method. |
| // Args: None. |
| // Return: None. |
| // Throws: None. |
| //-- |
| CMICmdCmdThreadInfo::CMICmdCmdThreadInfo( void ) |
| : m_bSingleThread( false ) |
| , m_bThreadInvalid( true ) |
| , m_constStrArgNamedThreadId( "thread-id" ) |
| { |
| // Command factory matches this name with that received from the stdin stream |
| m_strMiCmd = "thread-info"; |
| |
| // Required by the CMICmdFactory when registering *this command |
| m_pSelfCreatorFn = &CMICmdCmdThreadInfo::CreateSelf; |
| } |
| |
| //++ ------------------------------------------------------------------------------------ |
| // Details: CMICmdCmdThreadInfo destructor. |
| // Type: Overrideable. |
| // Args: None. |
| // Return: None. |
| // Throws: None. |
| //-- |
| CMICmdCmdThreadInfo::~CMICmdCmdThreadInfo( void ) |
| { |
| m_vecMIValueTuple.clear(); |
| } |
| |
| //++ ------------------------------------------------------------------------------------ |
| // 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 CMICmdCmdThreadInfo::ParseArgs( void ) |
| { |
| bool bOk = m_setCmdArgs.Add( *(new CMICmdArgValNumber( m_constStrArgNamedThreadId, false, true )) ); |
| 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 CMICmdCmdThreadInfo::Execute( void ) |
| { |
| CMICMDBASE_GETOPTION( pArgThreadId, Number, m_constStrArgNamedThreadId ); |
| MIuint nThreadId = 0; |
| if( pArgThreadId->GetFound() && pArgThreadId->GetValid() ) |
| { |
| m_bSingleThread = true; |
| nThreadId = static_cast< MIuint >( pArgThreadId->GetValue() ); |
| } |
| |
| CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); |
| lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess; |
| lldb::SBThread thread = rProcess.GetSelectedThread(); |
| |
| if( m_bSingleThread ) |
| { |
| thread = rProcess.GetThreadByIndexID( nThreadId ); |
| m_bThreadInvalid = thread.IsValid(); |
| if( !m_bThreadInvalid ) |
| return MIstatus::success; |
| |
| CMICmnMIValueTuple miTuple; |
| if( !rSessionInfo.MIResponseFormThreadInfo( m_cmdData, thread, miTuple ) ) |
| return MIstatus::failure; |
| |
| m_miValueTupleThread = miTuple; |
| |
| return MIstatus::success; |
| } |
| |
| // Multiple threads |
| m_vecMIValueTuple.clear(); |
| const MIuint nThreads = rProcess.GetNumThreads(); |
| for( MIuint i = 0; i < nThreads; i++ ) |
| { |
| lldb::SBThread thread = rProcess.GetThreadAtIndex( i ); |
| if( thread.IsValid() ) |
| { |
| CMICmnMIValueTuple miTuple; |
| if( !rSessionInfo.MIResponseFormThreadInfo( m_cmdData, thread, miTuple ) ) |
| return MIstatus::failure; |
| |
| m_vecMIValueTuple.push_back( miTuple ); |
| } |
| } |
| |
| 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 CMICmdCmdThreadInfo::Acknowledge( void ) |
| { |
| if( m_bSingleThread ) |
| { |
| if( !m_bThreadInvalid ) |
| { |
| const CMICmnMIValueConst miValueConst( "invalid thread id" ); |
| const CMICmnMIValueResult miValueResult( "msg", miValueConst ); |
| const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); |
| m_miResultRecord = miRecordResult; |
| return MIstatus::success; |
| } |
| |
| // MI print "%s^done,threads=[{id=\"%d\",target-id=\"%s\",frame={},state=\"%s\"}] |
| const CMICmnMIValueList miValueList( m_miValueTupleThread ); |
| const CMICmnMIValueResult miValueResult( "threads", miValueList ); |
| const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); |
| m_miResultRecord = miRecordResult; |
| return MIstatus::success; |
| } |
| |
| // Build up a list of thread information from tuples |
| VecMIValueTuple_t::const_iterator it = m_vecMIValueTuple.begin(); |
| if( it == m_vecMIValueTuple.end() ) |
| { |
| const CMICmnMIValueConst miValueConst( "[]" ); |
| const CMICmnMIValueResult miValueResult( "threads", miValueConst ); |
| const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); |
| m_miResultRecord = miRecordResult; |
| return MIstatus::success; |
| } |
| CMICmnMIValueList miValueList( *it ); |
| ++it; |
| while( it != m_vecMIValueTuple.end() ) |
| { |
| const CMICmnMIValueTuple & rTuple( *it ); |
| miValueList.Add( rTuple ); |
| |
| // Next |
| ++it; |
| } |
| |
| const CMICmnMIValueResult miValueResult( "threads", miValueList ); |
| const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, 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 * CMICmdCmdThreadInfo::CreateSelf( void ) |
| { |
| return new CMICmdCmdThreadInfo(); |
| } |