//++ ------------------------------------------------------------------------------------ // Details: Register with the debugger, the SBListener, the type of events you are interested // in. Others, like commands, may have already set the mask. // Type: Method. // Args: vClientName - (R) ID of the client who wants these events set. // vBroadcaster - (R) An SBBroadcaster's derived class. // vEventMask - (R) The mask of events to listen for. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- bool CMICmnLLDBDebugger::RegisterForEvent(const CMIUtilString &vClientName, const lldb::SBBroadcaster &vBroadcaster, const MIuint vEventMask) { const char *pBroadcasterName = vBroadcaster.GetName(); if (pBroadcasterName == nullptr) { SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_BROADCASTER_NAME), MIRSRC(IDS_WORD_INVALIDNULLPTR))); return MIstatus::failure; } CMIUtilString broadcasterName(pBroadcasterName); if (broadcasterName.length() == 0) { SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_BROADCASTER_NAME), MIRSRC(IDS_WORD_INVALIDEMPTY))); return MIstatus::failure; } MIuint existingMask = 0; if (!BroadcasterGetMask(broadcasterName, existingMask)) return MIstatus::failure; if (!ClientSaveMask(vClientName, broadcasterName, vEventMask)) return MIstatus::failure; MIuint eventMask = vEventMask; eventMask += existingMask; const MIuint result = m_lldbListener.StartListeningForEvents(vBroadcaster, eventMask); if (result == 0) { SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_STARTLISTENER), pBroadcasterName)); return MIstatus::failure; } return BroadcasterSaveMask(broadcasterName, eventMask); }
//++ ------------------------------------------------------------------------------------ // Details: Register a command's creator function with the command identifier the MI // command name i.e. 'file-exec-and-symbols'. // Type: Method. // Args: vMiCmd - (R) Command's name, the MI command. // vCmdCreateFn - (R) Command's creator function pointer. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- bool CMICmdFactory::CmdRegister(const CMIUtilString &vMiCmd, CmdCreatorFnPtr vCmdCreateFn) { if (!IsValid(vMiCmd)) { SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMDFACTORY_ERR_INVALID_CMD_NAME), vMiCmd.c_str())); return MIstatus::failure; } if (vCmdCreateFn == nullptr) { SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMDFACTORY_ERR_INVALID_CMD_CR8FN), vMiCmd.c_str())); return MIstatus::failure; } if (HaveAlready(vMiCmd)) { SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMDFACTORY_ERR_CMD_ALREADY_REGED), vMiCmd.c_str())); return MIstatus::failure; } MapPairMiCmdToCmdCreatorFn_t pr(vMiCmd, vCmdCreateFn); m_mapMiCmdToCmdCreatorFn.insert(pr); return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: Create a command given the specified MI command name. The command data object // contains the options for the command. // Type: Method. // Args: vMiCmd - (R) Command's name, the MI command. // vCmdData - (RW) Command's metadata status/information/result object. // vpNewCmd - (W) New command instance. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- bool CMICmdFactory::CmdCreate( const CMIUtilString & vMiCmd, const SMICmdData & vCmdData, CMICmdBase *& vpNewCmd ) { bool bOk = MIstatus::success; vpNewCmd = nullptr; if( !IsValid( vMiCmd ) ) { SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMDFACTORY_ERR_INVALID_CMD_NAME ), vMiCmd.c_str() ) ); return MIstatus::failure; } if( !HaveAlready( vMiCmd ) ) { SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMDFACTORY_ERR_CMD_NOT_REGISTERED ), vMiCmd.c_str() ) ); return MIstatus::failure; } const MapMiCmdToCmdCreatorFn_t::const_iterator it = m_mapMiCmdToCmdCreatorFn.find( vMiCmd ); const CMIUtilString & rMiCmd( (*it).first ); MIunused( rMiCmd ); CmdCreatorFnPtr pFn = (*it).second; CMICmdBase * pCmd = (*pFn)(); SMICmdData cmdData( vCmdData ); cmdData.id = pCmd->GetGUID(); bOk = pCmd->SetCmdData( cmdData ); if( bOk ) vpNewCmd = pCmd; return bOk; }
//++ ------------------------------------------------------------------------------------ // Details: Having previously had the potential command validated and found valid now // get the command executed. // If the Functionalityity returns MIstatus::failure call GetErrorDescription(). // This function is used by the application's main thread. // Type: Method. // Args: vCmdData - (RW) Command meta data. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- bool CMICmdMgr::CmdExecute(const SMICmdData &vCmdData) { bool bOk = MIstatus::success; // Pass the command's meta data structure to the command // so it can update it if required. (Need to copy it out of the // command before the command is deleted) CMICmdBase *pCmd = nullptr; bOk = m_factory.CmdCreate(vCmdData.strMiCmd, vCmdData, pCmd); if (!bOk) { const CMIUtilString errMsg( CMIUtilString::Format(MIRSRC(IDS_CMDMGR_ERR_CMD_FAILED_CREATE), m_factory.GetErrorDescription().c_str())); SetErrorDescription(errMsg); return MIstatus::failure; } bOk = m_invoker.CmdExecute(*pCmd); if (!bOk) { const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_CMDMGR_ERR_CMD_INVOKER), m_invoker.GetErrorDescription().c_str())); SetErrorDescription(errMsg); return MIstatus::failure; } return bOk; }
//++ ------------------------------------------------------------------------------------ // Details: Initialize resources for *this Stdin stream. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnStreamStdin::Initialize(void) { m_clientUsageRefCnt++; if (m_bInitialized) return MIstatus::success; bool bOk = MIstatus::success; CMIUtilString errMsg; // Note initialisation order is important here as some resources depend on previous MI::ModuleInit<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); MI::ModuleInit<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); MI::ModuleInit<CMICmnThreadMgrStd>(IDS_MI_INIT_ERR_THREADMGR, bOk, errMsg); #ifdef _MSC_VER MI::ModuleInit<CMICmnStreamStdinWindows>(IDS_MI_INIT_ERR_OS_STDIN_HANDLER, bOk, errMsg); bOk = bOk && SetOSStdinHandler(CMICmnStreamStdinWindows::Instance()); #else MI::ModuleInit<CMICmnStreamStdinLinux>(IDS_MI_INIT_ERR_OS_STDIN_HANDLER, bOk, errMsg); bOk = bOk && SetOSStdinHandler(CMICmnStreamStdinLinux::Instance()); #endif // ( _MSC_VER ) // The OS specific stdin stream handler must be set before *this class initialises if (bOk && m_pStdinReadHandler == nullptr) { CMIUtilString strInitError(CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_STREAMSTDIN_OSHANDLER), errMsg.c_str())); SetErrorDescription(strInitError); return MIstatus::failure; } // Other resources required if (bOk) { m_bKeyCtrlCHit = false; // Reset } m_bInitialized = bOk; if (!bOk) { CMIUtilString strInitError(CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_STREAMSTDIN), errMsg.c_str())); SetErrorDescription(strInitError); return MIstatus::failure; } return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: The callee client uses this function to write to the Logger. The data to be // written is given out to all the mediums registered. The verbosity type parameter // indicates to the medium(s) the type of data or message given to it. The medium has // modes of verbosity and depending on the verbosity set determines which writes // go in to the logger. // The logger must be initialized successfully before a write to any registered // can be carried out. // Type: Method. // Args: vData - (R) The data to write to the logger. // veType - (R) Verbosity type. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLog::Write(const CMIUtilString &vData, const ELogVerbosity veType) { if (!m_bInitialized && !m_bInitializingATM) return MIstatus::success; if (m_bRecursiveDive) return MIstatus::success; if (!m_bEnabled) return MIstatus::success; m_bRecursiveDive = true; MIuint cnt = 0; MIuint cntErr = 0; { MapMediumToName_t::const_iterator it = m_mapMediumToName.begin(); while (it != m_mapMediumToName.end()) { IMedium *pMedium = (*it).first; const CMIUtilString &rNameMedium = (*it).second; MIunused(rNameMedium); if (pMedium->Write(vData, veType)) cnt++; else cntErr++; // Next ++it; } } bool bOk = MIstatus::success; const MIuint mediumCnt = m_mapMediumToName.size(); if ((cnt == 0) && (mediumCnt > 0)) { SetErrorDescription(MIRSRC(IDS_LOG_MEDIUM_ERR_WRITE_ANY)); bOk = MIstatus::failure; } if (bOk && (cntErr != 0)) { SetErrorDescription(MIRSRC(IDS_LOG_MEDIUM_ERR_WRITE_MEDIUMFAIL)); bOk = MIstatus::failure; } m_bRecursiveDive = false; return bOk; }
//++ //------------------------------------------------------------------------------------ // Details: Initialise resources for *this thread manager. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnThreadMgrStd::Initialize() { m_clientUsageRefCnt++; if (m_bInitialized) return MIstatus::success; bool bOk = MIstatus::success; ClrErrorDescription(); CMIUtilString errMsg; // Note initialisation order is important here as some resources depend on // previous MI::ModuleInit<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); MI::ModuleInit<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); m_bInitialized = bOk; if (!bOk) { CMIUtilString strInitError(CMIUtilString::Format( MIRSRC(IDS_MI_INIT_ERR_THREADMGR), errMsg.c_str())); SetErrorDescription(strInitError); return MIstatus::failure; } return bOk; }
//++ ------------------------------------------------------------------------------------ // Details: Set up the events from the SBDebugger's we would like to listen to. // Type: Method. // Args: None. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- bool CMICmnLLDBDebugger::InitSBListener() { m_lldbListener = m_lldbDebugger.GetListener(); if (!m_lldbListener.IsValid()) { SetErrorDescription(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDLISTENER)); return MIstatus::failure; } const CMIUtilString strDbgId("CMICmnLLDBDebugger1"); MIuint eventMask = lldb::SBTarget::eBroadcastBitBreakpointChanged | lldb::SBTarget::eBroadcastBitModulesLoaded | lldb::SBTarget::eBroadcastBitModulesUnloaded | lldb::SBTarget::eBroadcastBitWatchpointChanged | lldb::SBTarget::eBroadcastBitSymbolsLoaded; bool bOk = RegisterForEvent(strDbgId, CMIUtilString(lldb::SBTarget::GetBroadcasterClassName()), eventMask); eventMask = lldb::SBThread::eBroadcastBitStackChanged; bOk = bOk && RegisterForEvent(strDbgId, CMIUtilString(lldb::SBThread::GetBroadcasterClassName()), eventMask); eventMask = lldb::SBProcess::eBroadcastBitStateChanged | lldb::SBProcess::eBroadcastBitInterrupt | lldb::SBProcess::eBroadcastBitSTDOUT | lldb::SBProcess::eBroadcastBitSTDERR | lldb::SBProcess::eBroadcastBitProfileData; bOk = bOk && RegisterForEvent(strDbgId, CMIUtilString(lldb::SBProcess::GetBroadcasterClassName()), eventMask); eventMask = lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived | lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit | lldb::SBCommandInterpreter::eBroadcastBitAsynchronousOutputData | lldb::SBCommandInterpreter::eBroadcastBitAsynchronousErrorData; bOk = bOk && RegisterForEvent(strDbgId, m_lldbDebugger.GetCommandInterpreter().GetBroadcaster(), eventMask); return bOk; }
//++ //------------------------------------------------------------------------------------ // Details: Unregister with the debugger, the SBListener, the type of events you // are no // longer interested in. Others, like commands, may still remain // interested so // an event may not necessarily be stopped. // Type: Method. // Args: vClientName - (R) ID of the client who no longer requires // these events. // vBroadcasterClass - (R) The SBBroadcaster's class name. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- bool CMICmnLLDBDebugger::UnregisterForEvent( const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass) { MIuint clientsEventMask = 0; if (!ClientGetTheirMask(vClientName, vBroadcasterClass, clientsEventMask)) return MIstatus::failure; if (!ClientRemoveTheirMask(vClientName, vBroadcasterClass)) return MIstatus::failure; const MIuint otherClientsEventMask = ClientGetMaskForAllClients(vBroadcasterClass); MIuint newEventMask = 0; for (MIuint i = 0; i < 32; i++) { const MIuint bit = 1 << i; const MIuint clientBit = bit & clientsEventMask; const MIuint othersBit = bit & otherClientsEventMask; if ((clientBit != 0) && (othersBit == 0)) { newEventMask += clientBit; } } const char *pBroadCasterName = vBroadcasterClass.c_str(); if (!m_lldbListener.StopListeningForEventClass( m_lldbDebugger, pBroadCasterName, newEventMask)) { SetErrorDescription( CMIUtilString::Format(MIRSRC(IDS_LLDBDEBUGGER_ERR_STOPLISTENER), vClientName.c_str(), pBroadCasterName)); return MIstatus::failure; } return BroadcasterSaveMask(vBroadcasterClass, otherClientsEventMask); }
//++ ------------------------------------------------------------------------------------ // Details: Determine and form the medium file's directory path and name. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLogMediumFile::FileFormFileNamePath() { ClrErrorDescription(); m_fileNamePath = MIRSRC(IDS_MEDIUMFILE_ERR_INVALID_PATH); if (m_strMediumFileDirectory.compare(MIRSRC(IDS_MEDIUMFILE_ERR_INVALID_PATH)) != 0) { CMIUtilDateTimeStd date; m_strMediumFileName = CMIUtilString::Format(m_constMediumFileNameFormat.c_str(), date.GetDateTimeLogFilename().c_str()); #if defined(_MSC_VER) m_fileNamePath = CMIUtilString::Format("%s\\%s", m_strMediumFileDirectory.c_str(), m_strMediumFileName.c_str()); #else m_fileNamePath = CMIUtilString::Format("%s/%s", m_strMediumFileDirectory.c_str(), m_strMediumFileName.c_str()); #endif // defined ( _MSC_VER ) return MIstatus::success; } SetErrorDescription(MIRSRC(IDE_MEDIUMFILE_ERR_GET_FILE_PATHNAME_SYS)); return MIstatus::failure; }
//++ ------------------------------------------------------------------------------------ // Details: Write text data to stderr. The text data does not need to // include a carriage line return as this is added to the text. The function also // then passes the text data into the CMICmnLog logger. // Type: Method. // Args: vText - (R) Text data. May be prefixed with MI app's short name. // vTxtForLogFile - (R) Text data. // vbSendToLog - (R) True = Yes send to the Log file too, false = do not. (Dflt = true) // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnStreamStderr::WritePriv(const CMIUtilString &vText, const CMIUtilString &vTxtForLogFile, const bool vbSendToLog /* = true */) { if (vText.length() == 0) return MIstatus::failure; bool bOk = MIstatus::success; { // Grab the stderr thread lock while we print CMIUtilThreadLock _lock(m_mutex); // Send this text to stderr const MIint status = ::fputs(vText.c_str(), stderr); if (status == EOF) { const CMIUtilString errMsg(CMIUtilString::Format(MIRSRC(IDS_STDERR_ERR_NOT_ALL_DATA_WRITTEN), vText.c_str())); SetErrorDescription(errMsg); bOk = MIstatus::failure; } else { ::fprintf(stderr, "\n"); ::fflush(stderr); } // Send this text to the log if (bOk && vbSendToLog) bOk &= m_pLog->WriteLog(vTxtForLogFile); } return bOk; }
//++ ------------------------------------------------------------------------------------ // Details: Determine and form the medium file's directory path and name. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLogMediumFile::FileFormFileNamePath( void ) { ClrErrorDescription(); m_fileNamePath = MIRSRC( IDS_MEDIUMFILE_ERR_INVALID_PATH ); CMIUtilString strPathName; if( CMIUtilSystem().GetLogFilesPath( strPathName ) ) { const CMIUtilString strPath = CMIUtilFileStd().StripOffFileName( strPathName ); // ToDo: Review this LINUX log file quick fix so not hidden // AD: // Linux was creating a log file here called '.\log.txt'. The '.' on linux // signifies that this file is 'hidden' and not normally visible. A quick fix // is to remove the path component all together. Linux also normally uses '/' // as directory separators, again leading to the problem of the hidden log. #if defined ( _MSC_VER ) m_fileNamePath = CMIUtilString::Format( "%s\\%s", strPath.c_str(), m_constMediumFileName.c_str() ); #else m_fileNamePath = CMIUtilString::Format( "%s", m_constMediumFileName.c_str() ); #endif // defined ( _MSC_VER ) return MIstatus::success; } SetErrorDescription( MIRSRC( IDE_MEDIUMFILE_ERR_GET_FILE_PATHNAME_SYS ) ); return MIstatus::failure; }
//++ ------------------------------------------------------------------------------------ // Details: Initialize resources for *this Stdin stream. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnStreamStdin::Initialize(void) { m_clientUsageRefCnt++; if (m_bInitialized) return MIstatus::success; bool bOk = MIstatus::success; CMIUtilString errMsg; // Note initialisation order is important here as some resources depend on previous MI::ModuleInit<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); MI::ModuleInit<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); if (bOk) { m_pCmdBuffer = new MIchar[m_constBufferSize]; } else { CMIUtilString strInitError(CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_STREAMSTDIN), errMsg.c_str())); SetErrorDescription(strInitError); return MIstatus::failure; } m_bInitialized = bOk; return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: Initialize resources for *this Stdin stream. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnStreamStdinLinux::Initialize( void ) { if( m_bInitialized ) return MIstatus::success; bool bOk = MIstatus::success; CMIUtilString errMsg; // Note initialisation order is important here as some resources depend on previous MI::ModuleInit< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg ); MI::ModuleInit< CMICmnResources >( IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg ); // Other resources required if( bOk ) { m_pCmdBuffer = new MIchar[ m_constBufferSize ]; m_pStdin = stdin; } // Clear error indicators for std input ::clearerr( stdin ); m_bInitialized = bOk; if( !bOk ) { CMIUtilString strInitError( CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_OS_STDIN_HANDLER ), errMsg.c_str() ) ); SetErrorDescription( strInitError ); return MIstatus::failure; } return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: Initialize *this manager. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMIDriverMgr::Initialize( void ) { m_clientUsageRefCnt++; ClrErrorDescription(); if( m_bInitialized ) return MIstatus::success; bool bOk = MIstatus::success; CMIUtilString errMsg; // Note initialisation order is important here as some resources depend on previous MI::ModuleInit< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg ); MI::ModuleInit< CMICmnResources >( IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg ); if( bOk ) { MIUtilTermios::StdinTermiosSet(); } m_bInitialized = bOk; if( !bOk ) { CMIUtilString strInitError( CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_DRIVERMGR ), errMsg.c_str() ) ); SetErrorDescription( strInitError ); return MIstatus::failure; } return bOk; }
//++ // Details: Set MI's error condition description. This may be accessed by // clients and // seen by users. Message is available to the client using the server // and sent // to the Logger. // Type: Method. // Args: vFormat - (R) Format string. // ... - (R) Variable number of CMIUtilString type objects. // Return: None. // Throws: None. //-- void CMICmnBase::SetErrorDescriptionn(const char *vFormat, ...) const { va_list args; va_start(args, vFormat); CMIUtilString strResult = CMIUtilString::FormatValist(vFormat, args); va_end(args); SetErrorDescription(strResult); }
//++ ------------------------------------------------------------------------------------ // Details: Execute commands from command source file in specified mode, and // set exit-flag if needed. // Type: Method. // Args: vbAsyncMode - (R) True = execute commands in asynchronous mode, false = otherwise. // Return: MIstatus::success - Function succeeded. // MIstatus::failure - Function failed. // Throws: None. //-- bool CMIDriver::ExecuteCommandFile(const bool vbAsyncMode) { std::ifstream ifsStartScript(m_strCmdLineArgCommandFileNamePath.c_str()); if (!ifsStartScript.is_open()) { const CMIUtilString errMsg( CMIUtilString::Format(MIRSRC(IDS_UTIL_FILE_ERR_OPENING_FILE_UNKNOWN), m_strCmdLineArgCommandFileNamePath.c_str())); SetErrorDescription(errMsg.c_str()); const bool bForceExit = true; SetExitApplicationFlag(bForceExit); return MIstatus::failure; } // Switch lldb to synchronous mode CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); const bool bAsyncSetting = rSessionInfo.GetDebugger().GetAsync(); rSessionInfo.GetDebugger().SetAsync(vbAsyncMode); // Execute commands from file bool bOk = MIstatus::success; CMIUtilString strCommand; while (!m_bExitApp && std::getline(ifsStartScript, strCommand)) { // Print command bOk = CMICmnStreamStdout::TextToStdout(strCommand); // Skip if it's a comment or empty line if (strCommand.empty() || strCommand[0] == '#') continue; // Execute if no error if (bOk) { CMIUtilThreadLock lock(rSessionInfo.GetSessionMutex()); bOk = InterpretCommand(strCommand); } // Draw the prompt after command will be executed (if enabled) bOk = bOk && CMICmnStreamStdout::WritePrompt(); // Exit if there is an error if (!bOk) { const bool bForceExit = true; SetExitApplicationFlag(bForceExit); break; } // Wait while the handler thread handles incoming events CMICmnLLDBDebugger::Instance().WaitForHandleEvent(); } // Switch lldb back to initial mode rSessionInfo.GetDebugger().SetAsync(bAsyncSetting); return bOk; }
//++ ------------------------------------------------------------------------------------ // Details: Initialize the LLDB Debugger object. // Type: Method. // Args: None. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- bool CMICmnLLDBDebugger::InitSBDebugger( void ) { m_lldbDebugger = lldb::SBDebugger::Create( false ); if( m_lldbDebugger.IsValid() ) return MIstatus::success; SetErrorDescription( MIRSRC( IDS_LLDBDEBUGGER_ERR_INVALIDDEBUGGER ) ); return MIstatus::failure; }
//++ ------------------------------------------------------------------------------------ // Details: Initialize setup *this driver ready for use. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMIDriver::Initialize( void ) { m_eCurrentDriverState = eDriverState_Initialising; m_clientUsageRefCnt++; ClrErrorDescription(); if( m_bInitialized ) return MIstatus::success; bool bOk = MIstatus::success; CMIUtilString errMsg; // Initialize all of the modules we depend on MI::ModuleInit< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg ); MI::ModuleInit< CMICmnStreamStdout >( IDS_MI_INIT_ERR_STREAMSTDOUT , bOk, errMsg ); MI::ModuleInit< CMICmnStreamStderr >( IDS_MI_INIT_ERR_STREAMSTDERR , bOk, errMsg ); MI::ModuleInit< CMICmnResources > ( IDS_MI_INIT_ERR_RESOURCES , bOk, errMsg ); MI::ModuleInit< CMICmnThreadMgrStd >( IDS_MI_INIT_ERR_THREADMANAGER, bOk, errMsg ); MI::ModuleInit< CMICmnStreamStdin > ( IDS_MI_INIT_ERR_STREAMSTDIN , bOk, errMsg ); MI::ModuleInit< CMICmdMgr > ( IDS_MI_INIT_ERR_CMDMGR , bOk, errMsg ); bOk &= m_rLldbDebugger.SetDriver( *this ); MI::ModuleInit< CMICmnLLDBDebugger >( IDS_MI_INIT_ERR_LLDBDEBUGGER , bOk, errMsg ); #if MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER CMIDriverMgr & rDrvMgr = CMIDriverMgr::Instance(); bOk = bOk && rDrvMgr.RegisterDriver( *g_driver, "LLDB driver" ); // Will be pass thru driver if( bOk ) { bOk = SetEnableFallThru( false ); // This is intentional at this time - yet to be fully implemented bOk = bOk && SetDriverToFallThruTo( *g_driver ); CMIUtilString strOtherDrvErrMsg; if( bOk && GetEnableFallThru() && !g_driver->MISetup( strOtherDrvErrMsg ) ) { bOk = false; errMsg = CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_FALLTHRUDRIVER ), strOtherDrvErrMsg.c_str() ); } } #endif // MICONFIG_COMPILE_MIDRIVER_WITH_LLDBDRIVER m_bExitApp = false; bOk = bOk && InitClientIDEToMIDriver(); // Init Eclipse IDE m_bInitialized = bOk; if( !bOk ) { const CMIUtilString msg = CMIUtilString::Format( MIRSRC( IDS_MI_INIT_ERR_DRIVER ), errMsg.c_str() ); SetErrorDescription( msg ); return MIstatus::failure; } m_eCurrentDriverState = eDriverState_RunningNotDebugging; return bOk; }
//++ //------------------------------------------------------------------------------------ // Details: Initialize the LLDB Debugger object. // Type: Method. // Args: None. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- bool CMICmnLLDBDebugger::InitSBDebugger() { m_lldbDebugger = lldb::SBDebugger::Create(false); if (!m_lldbDebugger.IsValid()) { SetErrorDescription(MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDDEBUGGER)); return MIstatus::failure; } m_lldbDebugger.GetCommandInterpreter().SetPromptOnQuit(false); return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: Initialize resources for *this debugger object. // Type: Method. // Args: None. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- bool CMICmnLLDBDebugger::Initialize() { m_clientUsageRefCnt++; if (m_bInitialized) return MIstatus::success; bool bOk = MIstatus::success; CMIUtilString errMsg; ClrErrorDescription(); if (m_pClientDriver == nullptr) { bOk = false; errMsg = MIRSRC(IDS_LLDBDEBUGGER_ERR_CLIENTDRIVER); } // Note initialization order is important here as some resources depend on previous MI::ModuleInit<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); MI::ModuleInit<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); MI::ModuleInit<CMICmnThreadMgrStd>(IDS_MI_INIT_ERR_THREADMGR, bOk, errMsg); MI::ModuleInit<CMICmnLLDBDebuggerHandleEvents>(IDS_MI_INIT_ERR_OUTOFBANDHANDLER, bOk, errMsg); MI::ModuleInit<CMICmnLLDBDebugSessionInfo>(IDS_MI_INIT_ERR_DEBUGSESSIONINFO, bOk, errMsg); // Note order is important here! if (bOk) lldb::SBDebugger::Initialize(); if (bOk && !InitSBDebugger()) { bOk = false; if (!errMsg.empty()) errMsg += ", "; errMsg += GetErrorDescription().c_str(); } if (bOk && !InitSBListener()) { bOk = false; if (!errMsg.empty()) errMsg += ", "; errMsg += GetErrorDescription().c_str(); } bOk = bOk && InitStdStreams(); bOk = bOk && RegisterMISummaryProviders(); m_bInitialized = bOk; if (!bOk && !HaveErrorDescription()) { CMIUtilString strInitError(CMIUtilString::Format(MIRSRC(IDS_MI_INIT_ERR_LLDBDEBUGGER), errMsg.c_str())); SetErrorDescription(strInitError); } return bOk; }
//++ //------------------------------------------------------------------------------------ // Details: Retrieve the client's event mask used for on a particular // SBBroadcaster. // Type: Method. // Args: vClientName - (R) The Client's unique ID. // vBroadcasterClass - (R) The SBBroadcaster's class name. // vwEventMask - (W) The client's mask. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- bool CMICmnLLDBDebugger::ClientGetTheirMask( const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass, MIuint &vwEventMask) { vwEventMask = 0; if (vClientName.empty()) { SetErrorDescription(CMIUtilString::Format( MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME), vClientName.c_str())); return MIstatus::failure; } const CMIUtilString strId(vBroadcasterClass + vClientName); const MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.find(strId); if (it != m_mapIdToEventMask.end()) { vwEventMask = (*it).second; } SetErrorDescription(CMIUtilString::Format( MIRSRC(IDS_LLDBDEBUGGER_ERR_CLIENTNOTREGISTERED), vClientName.c_str())); return MIstatus::failure; }
//++ ------------------------------------------------------------------------------------ // Details: Set the current running state of the MI Driver to running and currently not in // a debug session. // Type: Method. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Return: DriverState_e - The current running state of the application. // Throws: None. //-- bool CMIDriver::SetDriverStateRunningNotDebugging(void) { // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM if (m_eCurrentDriverState == eDriverState_RunningNotDebugging) return MIstatus::success; // Driver cannot be in the following states to set eDriverState_RunningNotDebugging switch (m_eCurrentDriverState) { case eDriverState_NotRunning: case eDriverState_Initialising: case eDriverState_ShuttingDown: { SetErrorDescription(MIRSRC(IDS_DRIVER_ERR_DRIVER_STATE_ERROR)); return MIstatus::failure; } case eDriverState_RunningDebugging: case eDriverState_RunningNotDebugging: break; case eDriverState_count: SetErrorDescription( CMIUtilString::Format(MIRSRC(IDS_CODE_ERR_INVALID_ENUMERATION_VALUE), "SetDriverStateRunningNotDebugging()")); return MIstatus::failure; } // Driver must be in this state to set eDriverState_RunningNotDebugging if (m_eCurrentDriverState != eDriverState_RunningDebugging) { SetErrorDescription(MIRSRC(IDS_DRIVER_ERR_DRIVER_STATE_ERROR)); return MIstatus::failure; } m_eCurrentDriverState = eDriverState_RunningNotDebugging; return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: Given the SBBroadcaster class name save it's current event mask. // Type: Method. // Args: vBroadcasterClass - (R) The SBBroadcaster's class name. // vEventMask - (R) The mask of events to listen for. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- bool CMICmnLLDBDebugger::BroadcasterSaveMask( const CMIUtilString & vBroadcasterClass, const MIuint vEventMask ) { if( vBroadcasterClass.empty() ) { SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER ), vBroadcasterClass.c_str() ) ); return MIstatus::failure; } BroadcasterRemoveMask( vBroadcasterClass ); MapPairBroadcastClassNameToEventMask_t pr( vBroadcasterClass, vEventMask ); m_mapBroadcastClassNameToEventMask.insert( pr ); return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: Return the resolved file's path for the given file. // Type: Method. // Args: vCmdData - (R) A command's information. // vPath - (R) Original path. // vwrResolvedPath - (W) Resolved path. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::ResolvePath( const SMICmdData & vCmdData, const CMIUtilString & vPath, CMIUtilString & vwrResolvedPath ) { // ToDo: Verify this code as it does not work as vPath is always empty CMIUtilString strResolvedPath; if( !SharedDataRetrieve( "Working Directory", strResolvedPath ) ) { vwrResolvedPath = ""; SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_SHARED_DATA_NOT_FOUND ), vCmdData.strMiCmd.c_str(), "Working Directory" ) ); return MIstatus::failure; } vwrResolvedPath = vPath; return ResolvePath( strResolvedPath, vwrResolvedPath ); }
//++ ------------------------------------------------------------------------------------ // Details: Given the client save its particular event requirements. // Type: Method. // Args: vClientName - (R) The Client's unique ID. // vBroadcasterClass - (R) The SBBroadcaster's class name targeted for the events. // vEventMask - (R) The mask of events to listen for. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- bool CMICmnLLDBDebugger::ClientSaveMask( const CMIUtilString & vClientName, const CMIUtilString & vBroadcasterClass, const MIuint vEventMask ) { if( vClientName.empty() ) { SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME ), vClientName.c_str() ) ); return MIstatus::failure; } CMIUtilString strId( vBroadcasterClass ); strId += vClientName; ClientRemoveTheirMask( vClientName, vBroadcasterClass ); MapPairIdToEventMask_t pr( strId, vEventMask ); m_mapIdToEventMask.insert( pr ); return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: Given the SBBroadcaster class name retrieve it's current event mask. // Type: Method. // Args: vBroadcasterClass - (R) The SBBroadcaster's class name. // vEventMask - (W) The mask of events to listen for. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- bool CMICmnLLDBDebugger::BroadcasterGetMask( const CMIUtilString & vBroadcasterClass, MIuint & vwEventMask ) const { vwEventMask = 0; if( vBroadcasterClass.empty() ) { SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_LLDBDEBUGGER_ERR_INVALIDBROADCASTER ), vBroadcasterClass.c_str() ) ); return MIstatus::failure; } const MapBroadcastClassNameToEventMask_t::const_iterator it = m_mapBroadcastClassNameToEventMask.find( vBroadcasterClass ); if( it != m_mapBroadcastClassNameToEventMask.end() ) { vwEventMask = (*it).second; } return MIstatus::success; }
//++ //------------------------------------------------------------------------------------ // Details: Given the client remove it's particular event requirements. // Type: Method. // Args: vClientName - (R) The Client's unique ID. // vBroadcasterClass - (R) The SBBroadcaster's class name. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- bool CMICmnLLDBDebugger::ClientRemoveTheirMask( const CMIUtilString &vClientName, const CMIUtilString &vBroadcasterClass) { if (vClientName.empty()) { SetErrorDescription(CMIUtilString::Format( MIRSRC(IDS_LLDBDEBUGGER_ERR_INVALIDCLIENTNAME), vClientName.c_str())); return MIstatus::failure; } CMIUtilString strId(vBroadcasterClass); strId += vClientName; const MapIdToEventMask_t::const_iterator it = m_mapIdToEventMask.find(strId); if (it != m_mapIdToEventMask.end()) { m_mapIdToEventMask.erase(it); } return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // 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 CMICmdCmdExecInterrupt::Execute() { CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger(); CMIUtilString strCmd("process interrupt"); const lldb::ReturnStatus status = rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult, false); MIunused(status); // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM if (!CMIDriver::Instance().SetDriverStateRunningNotDebugging()) { const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription()); SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SET_NEW_DRIVER_STATE), strCmd.c_str(), rErrMsg.c_str())); return MIstatus::failure; } return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: Register a Medium with *this Logger. // Type: Method. // Args: vrMedium - (R) The medium to register. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLog::RegisterMedium(const IMedium &vrMedium) { if (HaveMediumAlready(vrMedium)) return MIstatus::success; IMedium *pMedium = const_cast<IMedium *>(&vrMedium); if (!pMedium->Initialize()) { const CMIUtilString &rStrMedName(pMedium->GetName()); const CMIUtilString &rStrMedErr(pMedium->GetError()); SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LOG_MEDIUM_ERR_INIT), rStrMedName.c_str(), rStrMedErr.c_str())); return MIstatus::failure; } MapPairMediumToName_t pr(pMedium, pMedium->GetName()); m_mapMediumToName.insert(pr); return MIstatus::success; }