//++ ------------------------------------------------------------------------------------ // Details: *this driver passes text commands to a fall through driver is it does not // understand them (the LLDB driver). // This function is used by the application's main thread. // Type: Method. // Args: vTextLine - (R) Text data representing a possible command. // vwbCmdYesValid - (W) True = Command valid, false = command not handled. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMIDriver::InterpretCommandFallThruDriver(const CMIUtilString &vTextLine, bool &vwbCmdYesValid) { MIunused(vTextLine); MIunused(vwbCmdYesValid); // ToDo: Implement when less urgent work to be done or decide remove as not required // bool bOk = MIstatus::success; // bool bCmdNotUnderstood = true; // if( bCmdNotUnderstood && GetEnableFallThru() ) //{ // CMIUtilString errMsg; // bOk = DoFallThruToAnotherDriver( vStdInBuffer, errMsg ); // if( !bOk ) // { // errMsg = errMsg.StripCREndOfLine(); // errMsg = errMsg.StripCRAll(); // const CMIDriverBase * pOtherDriver = GetDriverToFallThruTo(); // const char * pName = pOtherDriver->GetDriverName().c_str(); // const char * pId = pOtherDriver->GetDriverId().c_str(); // const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_ERR_FALLTHRU_DRIVER_ERR ), pName, pId, errMsg.c_str() ) //); // m_pLog->WriteMsg( msg ); // } //} // // vwbCmdYesValid = bOk; // CMIUtilString strNot; // if( vwbCmdYesValid) // strNot = CMIUtilString::Format( "%s ", MIRSRC( IDS_WORD_NOT ) ); // const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_FALLTHRU_DRIVER_CMD_RECEIVED ), vTextLine.c_str(), strNot.c_str() ) ); // m_pLog->WriteLog( msg ); 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: Retrieve the frame information from LLDB frame object. // Type: Method. // Args: vrFrame - (R) LLDB thread object. // vPc - (W) Address number. // vFnName - (W) Function name. // vFileName - (W) File name text. // vPath - (W) Full file name and path text. // vnLine - (W) File line number. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::GetFrameInfo(const lldb::SBFrame &vrFrame, lldb::addr_t &vwPc, CMIUtilString &vwFnName, CMIUtilString &vwFileName, CMIUtilString &vwPath, MIuint &vwnLine) { lldb::SBFrame &rFrame = const_cast<lldb::SBFrame &>(vrFrame); static char pBuffer[MAX_PATH]; const MIuint nBytes = rFrame.GetLineEntry().GetFileSpec().GetPath(&pBuffer[0], sizeof(pBuffer)); MIunused(nBytes); CMIUtilString strResolvedPath(&pBuffer[0]); const char *pUnkwn = "??"; if (!ResolvePath(pUnkwn, strResolvedPath)) return MIstatus::failure; vwPath = strResolvedPath; vwPc = rFrame.GetPC(); const char *pFnName = rFrame.GetFunctionName(); vwFnName = (pFnName != nullptr) ? pFnName : pUnkwn; const char *pFileName = rFrame.GetLineEntry().GetFileSpec().GetFilename(); vwFileName = (pFileName != nullptr) ? pFileName : pUnkwn; vwnLine = rFrame.GetLineEntry().GetLine(); return MIstatus::success; }
//++ //------------------------------------------------------------------------------------ // Details: This function allows *this driver to call functionality on the // parent driver // ask for information for example. // Type: Overrideable. // Args: vrOtherDriver - (R) Reference to another driver object. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMIDriverBase::SetDriverParent(const CMIDriverBase &vrOtherDriver) { MIunused(vrOtherDriver); // Do nothing - override and implement. Set m_pDriverParent. 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 CMICmdCmdExecContinue::Execute() { const char *pCmd = "continue"; CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); const lldb::ReturnStatus rtn = rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand(pCmd, m_lldbResult); MIunused(rtn); if (m_lldbResult.GetErrorSize() == 0) { // CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM if (!CMIDriver::Instance().SetDriverStateRunningDebugging()) { const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription()); SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SET_NEW_DRIVER_STATE), m_cmdData.strMiCmd.c_str(), rErrMsg.c_str())); return MIstatus::failure; } } else { // ToDo: Re-evaluate if this is required when application near finished as this is parsing LLDB error message // which seems a hack and is code brittle const char *pLldbErr = m_lldbResult.GetError(); const CMIUtilString strLldbMsg(CMIUtilString(pLldbErr).StripCREndOfLine()); if (strLldbMsg == "error: Process must be launched.") { CMIDriver::Instance().SetExitApplicationFlag(true); } } return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: Empty the map of invoked commands doing work. Command objects are deleted too. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- void CMICmdInvoker::CmdDeleteAll( void ) { CMICmdMgr & rMgr = CMICmdMgr::Instance(); MapCmdIdToCmd_t::const_iterator it = m_mapCmdIdToCmd.begin(); while( it != m_mapCmdIdToCmd.end() ) { const MIuint cmdId( (*it).first ); MIunused( cmdId ); CMICmdBase * pCmd = (*it).second; const CMIUtilString & rCmdName( pCmd->GetCmdData().strMiCmd ); MIunused( rCmdName ); rMgr.CmdDelete( pCmd->GetCmdData() ); // Next ++it; } m_mapCmdIdToCmd.clear(); }
//++ ------------------------------------------------------------------------------------ // Details: Retrieve the resource text data for the given resource ID. If a resource ID // cannot be found and error is given returning the ID of the resource that // cannot be located. // Type: Method. // Args: vResourceId - (R) MI resource ID. // vrwResourceString - (W) Text. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnResources::GetStringFromResource(const MIuint vResourceId, CMIUtilString &vrwResourceString) const { MapRscrIdToTextData_t::const_iterator it = m_mapRscrIdToTextData.find(vResourceId); if (it == m_mapRscrIdToTextData.end()) { // Check this is a static variable init that needs this before we are ready if (!m_bInitialized) { (const_cast<CMICmnResources *>(this))->Initialize(); it = m_mapRscrIdToTextData.find(vResourceId); if (it == m_mapRscrIdToTextData.end()) { vrwResourceString = MIRSRC(IDS_RESOURCES_ERR_STRING_TABLE_INVALID); return MIstatus::failure; } } if (it == m_mapRscrIdToTextData.end()) { vrwResourceString = CMIUtilString::Format(MIRSRC(IDS_RESOURCES_ERR_STRING_NOT_FOUND), vResourceId); return MIstatus::failure; } } const MIuint nRsrcId((*it).first); MIunused(nRsrcId); const MIchar *pRsrcData((*it).second); // Return result vrwResourceString = pRsrcData; return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: Carry out work to complete the GDB set option to prepare and send back information // asked for. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdGdbSet::OptionFnFallback( const CMIUtilString::VecString_t & vrWords ) { MIunused( vrWords ); // Do nothing - intentional. This is a fallback temporary action function to do nothing. // This allows the search for gdb-set options to always suceed when the option is not // found (implemented). return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: Retrieve the corresponding text assigned to the resource ID. // Type: Method. // Args: vResourceId - (R) MI resource ID. // Return: CMIUtilString - Resource text. // Throws: None. //-- CMIUtilString CMICmnResources::GetString(const MIuint vResourceId) const { CMIUtilString str; const bool bFound = GetStringFromResource(vResourceId, str); MIunused(bFound); assert(bFound); return str; }
//++ //------------------------------------------------------------------------------------ // 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 CMICmdCmdInterpreterExec::Execute() { CMICMDBASE_GETOPTION(pArgInterpreter, String, m_constStrArgNamedInterpreter); CMICMDBASE_GETOPTION(pArgCommand, String, m_constStrArgNamedCommand); // Handle the interpreter parameter by do nothing on purpose (set to 'handled' // in // the arg definition above) const CMIUtilString &rStrInterpreter(pArgInterpreter->GetValue()); MIunused(rStrInterpreter); const CMIUtilString &rStrCommand(pArgCommand->GetValue()); CMICmnLLDBDebugSessionInfo &rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance()); const lldb::ReturnStatus rtn = rSessionInfo.GetDebugger().GetCommandInterpreter().HandleCommand( rStrCommand.c_str(), m_lldbResult, true); MIunused(rtn); return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: Carry out work to complete the GDB show option 'target-async' to prepare // and send back the requested information. // Type: Method. // Args: vrWords - (R) List of additional parameters used by this option. // Return: MIstatus::success - Function succeeded. // MIstatus::failure - Function failed. // Throws: None. //-- bool CMICmdCmdGdbShow::OptionFnTargetAsync(const CMIUtilString::VecString_t &vrWords) { MIunused(vrWords); // Get async mode CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); const bool bAsyncMode = rSessionInfo.GetDebugger().GetAsync(); m_strValue = bAsyncMode ? "on" : "off"; 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 CMICmdCmdStackListLocals::Execute( void ) { CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread ); CMICMDBASE_GETOPTION( pArgFrame, OptionLong, m_constStrArgFrame ); // Retrieve the --thread option's thread ID (only 1) MIuint64 nThreadId = UINT64_MAX; if( pArgThread->GetFound() ) { if( !pArgThread->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nThreadId ) ) { SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgThread.c_str() ) ); return MIstatus::failure; } } MIuint64 nFrame = UINT64_MAX; if( pArgFrame->GetFound() ) { if( !pArgFrame->GetExpectedOption< CMICmdArgValNumber, MIuint64 >( nFrame ) ) { SetError( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_OPTION_NOT_FOUND ), m_cmdData.strMiCmd.c_str(), m_constStrArgFrame.c_str() ) ); return MIstatus::failure; } } CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess; lldb::SBThread thread = (nThreadId != UINT64_MAX) ? rProcess.GetThreadByIndexID( nThreadId ) : rProcess.GetSelectedThread(); m_bThreadInvalid = !thread.IsValid(); if( m_bThreadInvalid ) return MIstatus::success; const lldb::StopReason eStopReason = thread.GetStopReason(); if( (eStopReason == lldb::eStopReasonNone) || (eStopReason == lldb::eStopReasonInvalid) ) { m_bThreadInvalid = true; return MIstatus::success; } const MIuint nFrames = thread.GetNumFrames(); MIunused( nFrames ); lldb::SBFrame frame = (nFrame != UINT64_MAX) ? thread.GetFrameAtIndex( nFrame ) : thread.GetSelectedFrame(); CMICmnMIValueList miValueList( true ); const MIuint maskVarTypes = 0x0110; if( !rSessionInfo.MIResponseFormVariableInfo( frame, maskVarTypes, miValueList ) ) return MIstatus::failure; m_miValueList = miValueList; return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: Carry out work to complete the GDB show option 'language' to prepare // and send back the requested information. // Type: Method. // Args: vrWords - (R) List of additional parameters used by this option. // Return: MIstatus::success - Function succeeded. // MIstatus::failure - Function failed. // Throws: None. //-- bool CMICmdCmdGdbShow::OptionFnLanguage(const CMIUtilString::VecString_t &vrWords) { MIunused(vrWords); // Get current language CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBThread sbThread = rSessionInfo.GetProcess().GetSelectedThread(); const lldb::SBFrame sbFrame = sbThread.GetSelectedFrame(); lldb::SBCompileUnit sbCompileUnit = sbFrame.GetCompileUnit(); const lldb::LanguageType eLanguageType = sbCompileUnit.GetLanguage(); m_strValue = lldb::SBLanguageRuntime::GetNameForLanguageType(eLanguageType); 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: Retrieve breakpoint information and write into the given breakpoint information // object. Note not all possible information is retrieved and so the information // object may need to be filled in with more information after calling this // function. Mainly breakpoint location information of information that is // unlikely to change. // Type: Method. // Args: vBrkPt - (R) LLDB break point object. // vrBrkPtInfo - (W) Break point information object. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::GetBrkPtInfo(const lldb::SBBreakpoint &vBrkPt, SBrkPtInfo &vrwBrkPtInfo) const { lldb::SBBreakpoint &rBrkPt = const_cast<lldb::SBBreakpoint &>(vBrkPt); lldb::SBBreakpointLocation brkPtLoc = rBrkPt.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; MIunused(pModule); const char *pFile = pUnkwn; const char *pFn = pUnkwn; const char *pFilePath = pUnkwn; size_t nLine = 0; lldb::addr_t nAddr = brkPtAddr.GetLoadAddress(GetTarget()); if (nAddr == LLDB_INVALID_ADDRESS) nAddr = brkPtAddr.GetFileAddress(); 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(); } vrwBrkPtInfo.m_id = vBrkPt.GetID(); vrwBrkPtInfo.m_strType = "breakpoint"; vrwBrkPtInfo.m_pc = nAddr; vrwBrkPtInfo.m_fnName = pFn; vrwBrkPtInfo.m_fileName = pFile; vrwBrkPtInfo.m_path = pFilePath; vrwBrkPtInfo.m_nLine = nLine; vrwBrkPtInfo.m_nTimes = vBrkPt.GetHitCount(); 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: 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 CMICmdCmdExecFinish::Acknowledge() { if (m_lldbResult.GetErrorSize() > 0) { const char *pLldbErr = m_lldbResult.GetError(); MIunused(pLldbErr); const CMICmnMIValueConst miValueConst(m_lldbResult.GetError()); const CMICmnMIValueResult miValueResult("message", miValueConst); const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult); m_miResultRecord = miRecordResult; } else { const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); m_miResultRecord = miRecordResult; } return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: Search the registered drivers and return the first driver which says it is // not GDB/MI compatible i.e. the LLDB Driver class. // Type: Method. // Args: None. // Return: IDriver * - Ptr to driver, NULL = no driver found. // Throws: None. //-- CMIDriverMgr::IDriver * CMIDriverMgr::GetFirstNonMIDriver( void ) const { IDriver * pDriver = nullptr; MapDriverIdToDriver_t::const_iterator it = m_mapDriverIdToDriver.begin(); while( it != m_mapDriverIdToDriver.end() ) { const CMIUtilString & rDrvId = (*it).first; MIunused( rDrvId ); IDriver * pDvr = (*it).second; if( !pDvr->GetDriverIsGDBMICompatibleDriver() ) { pDriver = pDvr; break; } // Next ++it; } return pDriver; }
//++ ------------------------------------------------------------------------------------ // Details: Return the resolved file's path for the given file. // Type: Method. // Args: vstrUnknown - (R) String assigned to path when resolved path is empty. // vwrResolvedPath - (RW) The original path overwritten with resolved path. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::ResolvePath(const CMIUtilString &vstrUnknown, CMIUtilString &vwrResolvedPath) { if (vwrResolvedPath.size() < 1) { vwrResolvedPath = vstrUnknown; return MIstatus::success; } bool bOk = MIstatus::success; CMIUtilString::VecString_t vecPathFolders; const MIuint nSplits = vwrResolvedPath.Split("/", vecPathFolders); MIunused(nSplits); MIuint nFoldersBack = 1; // 1 is just the file (last element of vector) while (bOk && (vecPathFolders.size() >= nFoldersBack)) { CMIUtilString strTestPath; MIuint nFoldersToAdd = nFoldersBack; while (nFoldersToAdd > 0) { strTestPath += "/"; strTestPath += vecPathFolders[vecPathFolders.size() - nFoldersToAdd]; nFoldersToAdd--; } bool bYesAccessible = false; bOk = AccessPath(strTestPath, bYesAccessible); if (bYesAccessible) { vwrResolvedPath = strTestPath; return MIstatus::success; } else nFoldersBack++; } // No files exist in the union of working directory and debuginfo path // Simply use the debuginfo path and let the IDE handle it. 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. // Synopsis: -file-exec-and-symbols file // Ref: http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-File-Commands.html#GDB_002fMI-File-Commands // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdFileExecAndSymbols::Execute(void) { CMICMDBASE_GETOPTION(pArgNamedFile, File, m_constStrArgNameFile); CMICMDBASE_GETOPTION(pArgPlatformName, OptionShort, m_constStrArgNamedPlatformName); CMICMDBASE_GETOPTION(pArgRemotePath, OptionShort, m_constStrArgNamedRemotePath); CMICmdArgValFile *pArgFile = static_cast<CMICmdArgValFile *>(pArgNamedFile); const CMIUtilString &strExeFilePath(pArgFile->GetValue()); bool bPlatformName = pArgPlatformName->GetFound(); CMIUtilString platformName; if (bPlatformName) { pArgPlatformName->GetExpectedOption<CMICmdArgValString, CMIUtilString>(platformName); } CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBDebugger &rDbgr = rSessionInfo.GetDebugger(); lldb::SBError error; const char *pTargetTriple = nullptr; // Let LLDB discover the triple required const char *pTargetPlatformName = platformName.c_str(); const bool bAddDepModules = false; lldb::SBTarget target = rDbgr.CreateTarget(strExeFilePath.c_str(), pTargetTriple, pTargetPlatformName, bAddDepModules, error); CMIUtilString strWkDir; const CMIUtilString &rStrKeyWkDir(rSessionInfo.m_constStrSharedDataKeyWkDir); if (!rSessionInfo.SharedDataRetrieve<CMIUtilString>(rStrKeyWkDir, strWkDir)) { strWkDir = CMIUtilFileStd::StripOffFileName(strExeFilePath); if (!rSessionInfo.SharedDataAdd<CMIUtilString>(rStrKeyWkDir, strWkDir)) { SetError(CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_ADD), m_cmdData.strMiCmd.c_str(), rStrKeyWkDir.c_str())); return MIstatus::failure; } } if (!rDbgr.SetCurrentPlatformSDKRoot(strWkDir.c_str())) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FNFAILED), m_cmdData.strMiCmd.c_str(), "SetCurrentPlatformSDKRoot()")); return MIstatus::failure; } if (pArgRemotePath->GetFound()) { CMIUtilString remotePath; pArgRemotePath->GetExpectedOption<CMICmdArgValString, CMIUtilString>(remotePath); lldb::SBModule module = target.FindModule(target.GetExecutable()); if (module.IsValid()) { module.SetPlatformFileSpec(lldb::SBFileSpec(remotePath.c_str())); } } lldb::SBStream err; if (error.Fail()) { const bool bOk = error.GetDescription(err); MIunused(bOk); } if (!target.IsValid()) { SetError( CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET), m_cmdData.strMiCmd.c_str(), strExeFilePath.c_str(), err.GetData())); return MIstatus::failure; } if (error.Fail()) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_CREATE_TARGET), m_cmdData.strMiCmd.c_str(), err.GetData())); return MIstatus::failure; } return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: CDataObjectBase copy constructor. // Type: Method. // Args: vrOther - (R) The other object. // Return: None. // Throws: None. //-- CMIUtilVariant::CDataObjectBase::CDataObjectBase(const CDataObjectBase &vrOther) { MIunused(vrOther); }
//++ //------------------------------------------------------------------------------------ // Details: Set the MI Driver's exit application flag. The application checks // this flag // after every stdin line is read so the exit may not be instantaneous. // If vbForceExit is false the MI Driver queries its state and // determines if is // should exit or continue operating depending on that running state. // Type: Overrideable. // Args: vbForceExit - (R) True = Do not query, set state to exit, false = // query if can/should exit right now. // Return: None. // Throws: None. //-- void CMIDriverBase::SetExitApplicationFlag(const bool vbForceExit) { MIunused(vbForceExit); // Do nothing - override and implement }
//++ ------------------------------------------------------------------------------------ // Details: Given a set of command argument objects parse the context option string to // find those argument and retrieve their value. If the function fails call // GetArgsThatAreMissing() to see which commands that were mandatory were // missing or failed to parse. // Type: Method. // Args: vStrMiCmd - (R) Command's name. // vCmdArgsText - (RW) A command's options or argument. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdArgSet::Validate( const CMIUtilString & vStrMiCmd, CMICmdArgContext & vwCmdArgsText ) { m_cmdArgContext = vwCmdArgsText; // Iterate all the arguments or options required by a command const MIuint nArgs = vwCmdArgsText.GetNumberArgsPresent(); MIuint nArgsMandatoryCnt = 0; SetCmdArgs_t::const_iterator it = m_setCmdArgs.begin(); while( it != m_setCmdArgs.end() ) { const CMICmdArgValBase * pArg( *it ); const CMIUtilString & rArgName( pArg->GetName() ); MIunused( rArgName ); if( pArg->GetIsMandatory() ) nArgsMandatoryCnt++; if( !const_cast< CMICmdArgValBase * >( pArg )->Validate( vwCmdArgsText ) ) { if( pArg->GetIsMandatory() && !pArg->GetFound() ) m_setCmdArgsThatAreMissing.push_back( const_cast< CMICmdArgValBase * >( pArg ) ); else if( pArg->GetFound() ) { if( pArg->GetIsMissingOptions() ) m_setCmdArgsMissingInfo.push_back( const_cast< CMICmdArgValBase * >( pArg ) ); else if( !pArg->GetValid() ) m_setCmdArgsThatNotValid.push_back( const_cast< CMICmdArgValBase * >( pArg ) ); } } if( pArg->GetFound() && !pArg->GetIsHandledByCmd() ) { m_bIsArgsPresentButNotHandledByCmd = true; m_setCmdArgsNotHandledByCmd.push_back( const_cast< CMICmdArgValBase * >( pArg ) ); } // Next ++it; } // Check that one or more argument objects have any issues to report... if( nArgs < nArgsMandatoryCnt ) { SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMD_ARGS_ERR_N_OPTIONS_REQUIRED ), nArgsMandatoryCnt ) ); return MIstatus::failure; } if( !vwCmdArgsText.IsEmpty() ) { SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMD_ARGS_ERR_CONTEXT_NOT_ALL_EATTEN ), vwCmdArgsText.GetArgsLeftToParse().c_str() ) ); return MIstatus::failure; } if( IsArgsPresentButNotHandledByCmd() ) WarningArgsNotHandledbyCmdLogFile( vStrMiCmd ); CMIUtilString strListMissing; CMIUtilString strListInvalid; CMIUtilString strListMissingInfo; const bool bArgsMissing = (m_setCmdArgsThatAreMissing.size() > 0); const bool bArgsInvalid = (m_setCmdArgsThatNotValid.size() > 0); const bool bArgsMissingInfo = (m_setCmdArgsMissingInfo.size() > 0); if( !(bArgsMissing || bArgsInvalid || bArgsMissingInfo) ) return MIstatus::success; if( bArgsMissing ) { MIuint i = 0; SetCmdArgs_t::const_iterator it = m_setCmdArgsThatAreMissing.begin(); while( it != m_setCmdArgsThatAreMissing.end() ) { if( i++ > 0 ) strListMissing += m_constStrCommaSpc; const CMICmdArgValBase * pArg( *it ); strListMissing += pArg->GetName(); // Next ++it; } } if( bArgsInvalid ) { MIuint i = 0; SetCmdArgs_t::const_iterator it = m_setCmdArgsThatNotValid.begin(); while( it != m_setCmdArgsThatNotValid.end() ) { if( i++ > 0 ) strListMissing += m_constStrCommaSpc; const CMICmdArgValBase * pArg( *it ); strListInvalid += pArg->GetName(); // Next ++it; } } if( bArgsMissingInfo ) { MIuint i = 0; SetCmdArgs_t::const_iterator it = m_setCmdArgsMissingInfo.begin(); while( it != m_setCmdArgsMissingInfo.end() ) { if( i++ > 0 ) strListMissingInfo += m_constStrCommaSpc; const CMICmdArgValBase * pArg( *it ); strListMissingInfo += pArg->GetName(); // Next ++it; } } if( bArgsMissing && bArgsInvalid ) { SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMD_ARGS_ERR_VALIDATION_MAN_INVALID ), strListMissing.c_str(), strListInvalid.c_str() ) ); return MIstatus::failure; } if( bArgsMissing ) { SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMD_ARGS_ERR_VALIDATION_MANDATORY ), strListMissing.c_str() ) ); return MIstatus::failure; } if( bArgsMissingInfo ) { SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMD_ARGS_ERR_VALIDATION_MISSING_INF ), strListMissingInfo.c_str() ) ); return MIstatus::failure; } if( bArgsInvalid ) { SetErrorDescription( CMIUtilString::Format( MIRSRC( IDS_CMD_ARGS_ERR_VALIDATION_INVALID ), strListInvalid.c_str() ) ); return MIstatus::failure; } return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: CDataObjectBase move constructor. // Type: Method. // Args: vrwOther - (R) The other object. // Return: None. // Throws: None. //-- CMIUtilVariant::CDataObjectBase::CDataObjectBase(CDataObjectBase &&vrwOther) { MIunused(vrwOther); }
//++ ------------------------------------------------------------------------------------ // 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; } 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: Perform a bitwise copy of *this object. // Type: Overrideable. // Args: vrOther - (R) The other object. // Return: None. // Throws: None. //-- void CMIUtilVariant::CDataObjectBase::Copy(const CDataObjectBase &vrOther) { // Override to implement MIunused(vrOther); }
//++ ------------------------------------------------------------------------------------ // 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 CMICmdCmdInterpreterExec::Execute( void ) { CMICMDBASE_GETOPTION( pArgInterpreter, String, m_constStrArgNamedInterpreter ); CMICMDBASE_GETOPTION( pArgCommand, String, m_constStrArgNamedCommand ); const CMIUtilString & rStrInterpreter( pArgInterpreter->GetValue() ); const CMIUtilString & rStrCommand( pArgCommand->GetValue() ); const CMIUtilString strCmd( CMIUtilString::Format( "%s %s", rStrInterpreter.c_str(), rStrCommand.c_str() ) ); CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); const lldb::ReturnStatus rtn = rSessionInfo.m_rLldbDebugger.GetCommandInterpreter().HandleCommand( strCmd.c_str(), m_lldbResult, true ); MIunused( rtn ); return MIstatus::success; }