//===-- 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 #include // In-house headers: #include "MICmdCmdThread.h" #include "MICmnMIResultRecord.h" #include "MICmnMIValueConst.h" #include "MICmnLLDBDebugger.h" #include "MICmnLLDBDebugSessionInfo.h" #include "MICmdArgValNumber.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 )) ); 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 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.MIResponseFormThreadInfo3( 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.MIResponseFormThreadInfo3( 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(); }