//++ ------------------------------------------------------------------------------------ // Details: Form MI partial response by appending more MI value type objects to the // tuple type object past in. // Type: Method. // Args: vPc - (R) Address number. // vFnName - (R) Function name. // vFileName - (R) File name text. // vPath - (R) Full file name and path text. // vnLine - (R) File line number. // vwrMIValueTuple - (W) MI value tuple object. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::MIResponseFormBrkPtFrameInfo( const lldb::addr_t vPc, const CMIUtilString & vFnName, const CMIUtilString & vFileName, const CMIUtilString & vPath, const MIuint vnLine, CMICmnMIValueTuple & vwrMiValueTuple ) { const CMIUtilString strAddr( CMIUtilString::Format( "0x%08llx", vPc ) ); const CMICmnMIValueConst miValueConst2( strAddr ); const CMICmnMIValueResult miValueResult2( "addr", miValueConst2 ); if( !vwrMiValueTuple.Add( miValueResult2 ) ) return MIstatus::failure; const CMICmnMIValueConst miValueConst3( vFnName ); const CMICmnMIValueResult miValueResult3( "func", miValueConst3 ); if( !vwrMiValueTuple.Add( miValueResult3 ) ) return MIstatus::failure; const CMICmnMIValueConst miValueConst5( vFileName ); const CMICmnMIValueResult miValueResult5( "file", miValueConst5 ); if( !vwrMiValueTuple.Add( miValueResult5 ) ) return MIstatus::failure; const CMIUtilString strN5 = CMIUtilString::Format( "%s/%s", vPath.c_str(), vFileName.c_str() ); const CMICmnMIValueConst miValueConst6( strN5 ); const CMICmnMIValueResult miValueResult6( "fullname", miValueConst6 ); if( !vwrMiValueTuple.Add( miValueResult6 ) ) return MIstatus::failure; const CMIUtilString strLine( CMIUtilString::Format( "%d", vnLine ) ); const CMICmnMIValueConst miValueConst7( strLine ); const CMICmnMIValueResult miValueResult7( "line", miValueConst7 ); if( !vwrMiValueTuple.Add( miValueResult7 ) ) return MIstatus::failure; return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: Retrieve from the LLDB SB Value object the char value of the variable. // Type: Method. // Args: None. // Return: CMIUtilString - The char value of the variable. // Throws: None. //-- CMIUtilString CMICmnLLDBUtilSBValue::GetSimpleValueChar(void) const { const uint64_t value = m_rValue.GetValueAsUnsigned(); if (value == 0) { const uint64_t nFailValue = 1; if (nFailValue == m_rValue.GetValueAsUnsigned(nFailValue)) return m_pUnkwn; } const lldb::BasicType eType = m_rValue.GetType().GetBasicType(); switch (eType) { default: assert(0 && "value must be a char type"); case lldb::eBasicTypeChar: case lldb::eBasicTypeSignedChar: case lldb::eBasicTypeUnsignedChar: { const CMIUtilString prefix(CMIUtilString::ConvertToPrintableASCII((char)value)); return CMIUtilString::Format("%" PRIu8 " '%s'", (uint8_t)value, prefix.c_str()); } case lldb::eBasicTypeChar16: { const CMIUtilString prefix(CMIUtilString::ConvertToPrintableASCII((char16_t)value)); return CMIUtilString::Format("U+%04" PRIx16 " u'%s'", (uint16_t)value, prefix.c_str()); } case lldb::eBasicTypeChar32: { const CMIUtilString prefix(CMIUtilString::ConvertToPrintableASCII((char32_t)value)); return CMIUtilString::Format("U+%08" PRIx32 " U'%s'", (uint32_t)value, prefix.c_str()); } } }
//++ //------------------------------------------------------------------------------------ // 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: Retrieve from the LLDB SB Value object of type char[] the c-string value. // Type: Method. // Args: None. // Return: CMIUtilString - The c-string value of the variable. // Throws: None. //-- CMIUtilString CMICmnLLDBUtilSBValue::GetSimpleValueCStringArray(void) const { const MIuint nChildren = m_rValue.GetNumChildren(); lldb::SBValue child = m_rValue.GetChildAtIndex(0); const lldb::BasicType eType = child.GetType().GetBasicType(); switch (eType) { default: assert(0 && "value must be a char[] type"); case lldb::eBasicTypeChar: case lldb::eBasicTypeSignedChar: case lldb::eBasicTypeUnsignedChar: { // FIXME Add slashes before double quotes const CMIUtilString prefix(ReadCStringFromHostMemory<char>(m_rValue, nChildren).AddSlashes()); // TODO: to match char* it should be the following // return CMIUtilString::Format("[%u] \"%s\"", nChildren, prefix.c_str()); return CMIUtilString::Format("\"%s\"", prefix.c_str()); } case lldb::eBasicTypeChar16: { // FIXME Add slashes before double quotes const CMIUtilString prefix(ReadCStringFromHostMemory<char16_t>(m_rValue, nChildren).AddSlashes()); return CMIUtilString::Format("u\"%s\"", prefix.c_str()); } case lldb::eBasicTypeChar32: { // FIXME Add slashes before double quotes const CMIUtilString prefix(ReadCStringFromHostMemory<char32_t>(m_rValue, nChildren).AddSlashes()); return CMIUtilString::Format("U\"%s\"", prefix.c_str()); } } }
//++ // Details: Check if two strings share equal contents. // Type: Method. // Args: vrLhs - (R) String A. // vrRhs - (R) String B. // Return: bool - True = yes equal, false - different. // Throws: None. //-- bool CMIUtilString::Compare(const CMIUtilString &vrLhs, const CMIUtilString &vrRhs) { // Check the sizes match if (vrLhs.size() != vrRhs.size()) return false; return (::strncmp(vrLhs.c_str(), vrRhs.c_str(), vrLhs.size()) == 0); }
//++ ------------------------------------------------------------------------------------ // 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: Determine the given file path exists or not. // Type: Method. // Args: vPath - (R) File name path. // vwbYesAccessible - (W) True - file exists, false = does not exist. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::AccessPath( const CMIUtilString & vPath, bool & vwbYesAccessible ) { #ifdef _WIN32 vwbYesAccessible = (::_access( vPath.c_str(), 0 ) == 0); #else vwbYesAccessible = (::access( vPath.c_str(), 0 ) == 0); #endif // _WIN32 return MIstatus::success; }
//++ //------------------------------------------------------------------------------------ // Details: Perform a snprintf format style on a string data. A new string // object is // created and returned. // Type: Static method. // Args: vrFormat - (R) Format string data instruction. // vArgs - (R) Var list args of any type. // Return: CMIUtilString - Number of splits found in the string data. // Throws: None. //-- CMIUtilString CMIUtilString::FormatPriv(const CMIUtilString &vrFormat, va_list vArgs) { CMIUtilString strResult; MIint nFinal = 0; MIint n = vrFormat.size(); // IOR: mysterious crash in this function on some windows builds not able to // duplicate // but found article which may be related. Crash occurs in vsnprintf() or // va_copy() // Duplicate vArgs va_list argument pointer to ensure that it can be safely // used in // a new frame // http://julipedia.meroh.net/2011/09/using-vacopy-to-safely-pass-ap.html va_list argsDup; va_copy(argsDup, vArgs); // Create a copy va_list to reset when we spin va_list argsCpy; va_copy(argsCpy, argsDup); if (n == 0) return strResult; n = n << 4; // Reserve 16 times as much the length of the vrFormat std::unique_ptr<char[]> pFormatted; while (1) { pFormatted.reset(new char[n + 1]); // +1 for safety margin ::strncpy(&pFormatted[0], vrFormat.c_str(), n); // We need to restore the variable argument list pointer to the start again // before running vsnprintf() more then once va_copy(argsDup, argsCpy); nFinal = ::vsnprintf(&pFormatted[0], n, vrFormat.c_str(), argsDup); if ((nFinal < 0) || (nFinal >= n)) n += abs(nFinal - n + 1); else break; } va_end(argsCpy); va_end(argsDup); strResult = pFormatted.get(); return strResult; }
//++ // 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: vrTxt - (R) Text description. // Return: None. // Throws: None. //-- void CMICmnBase::SetErrorDescription(const CMIUtilString &vrTxt) const { m_strMILastErrorDescription = vrTxt; if (!vrTxt.empty()) { const CMIUtilString txt(CMIUtilString::Format("Error: %s", vrTxt.c_str())); CMICmnStreamStderr::Instance().Write(txt); } }
//++ ------------------------------------------------------------------------------------ // Details: Write data to existing opened file. // Type: Method. // Args: vData - (R) Text data. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMIUtilFileStd::Write( const CMIUtilString & vData ) { if( vData.size() == 0 ) return MIstatus::success; if( m_bFileError ) return MIstatus::failure; if( m_pFileHandle == nullptr ) { m_bFileError = true; SetErrorDescriptionn( MIRSRC( IDE_UTIL_FILE_ERR_WRITING_NOTOPEN ), m_fileNamePath.c_str() ); return MIstatus::failure; } // Get the string size MIuint size = vData.size(); if( ::fwrite( vData.c_str(), 1, size, m_pFileHandle ) == size ) { // Flush the data to the file ::fflush( m_pFileHandle ); return MIstatus::success; } // Not all of the data has been transferred m_bFileError = true; SetErrorDescriptionn( MIRSRC( IDE_UTIL_FILE_ERR_WRITING_FILE ), m_fileNamePath.c_str() ); return MIstatus::failure; }
//++ ------------------------------------------------------------------------------------ // Details: Interpret the text data and match against current commands to see if there // is a match. If a match then the command is issued and actioned on. If a // command cannot be found to match then vwbCmdYesValid is set to false and // nothing else is done here. // 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 invalid, false = command acted on. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMIDriver::InterpretCommandThisDriver( const CMIUtilString & vTextLine, bool & vwbCmdYesValid ) { vwbCmdYesValid = false; bool bCmdNotInCmdFactor = false; SMICmdData cmdData; CMICmdMgr & rCmdMgr = CMICmdMgr::Instance(); if( !rCmdMgr.CmdInterpret( vTextLine, vwbCmdYesValid, bCmdNotInCmdFactor, cmdData ) ) return MIstatus::failure; if( vwbCmdYesValid ) { // For debugging only //m_pLog->WriteLog( cmdData.strMiCmdAll.c_str() ); return ExecuteCommand( cmdData ); } // Write to the Log that a 'command' was not valid. // Report back to the MI client via MI result record. CMIUtilString strNotInCmdFactory; if( bCmdNotInCmdFactor ) strNotInCmdFactory = CMIUtilString::Format( MIRSRC( IDS_DRIVER_CMD_NOT_IN_FACTORY ), cmdData.strMiCmd.c_str() ); const CMIUtilString strNot( CMIUtilString::Format( "%s ", MIRSRC( IDS_WORD_NOT ) ) ); const CMIUtilString msg( CMIUtilString::Format( MIRSRC( IDS_DRIVER_CMD_RECEIVED ), vTextLine.c_str(), strNot.c_str(), strNotInCmdFactory.c_str() ) ); const CMICmnMIValueConst vconst = CMICmnMIValueConst( msg ); const CMICmnMIValueResult valueResult( "msg", vconst ); const CMICmnMIResultRecord miResultRecord( cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, valueResult ); m_rStdOut.WriteMIResponse( miResultRecord.GetString() ); // Proceed to wait for or execute next command return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: Release resources for *this Stdin stream. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnStreamStdin::Shutdown(void) { if (--m_clientUsageRefCnt > 0) return MIstatus::success; if (!m_bInitialized) return MIstatus::success; m_bInitialized = false; ClrErrorDescription(); if (m_pCmdBuffer != nullptr) { delete[] m_pCmdBuffer; m_pCmdBuffer = nullptr; } bool bOk = MIstatus::success; CMIUtilString errMsg; MI::ModuleShutdown<CMICmnResources>(IDE_MI_SHTDWN_ERR_RESOURCES, bOk, errMsg); MI::ModuleShutdown<CMICmnLog>(IDS_MI_SHTDWN_ERR_LOG, bOk, errMsg); if (!bOk) { SetErrorDescriptionn(MIRSRC(IDE_MI_SHTDWN_ERR_STREAMSTDIN), errMsg.c_str()); } 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 CMICmdCmdBreakCondition::Execute() { CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNamedNumber); CMICMDBASE_GETOPTION(pArgExpr, String, m_constStrArgNamedExpr); m_nBrkPtId = pArgNumber->GetValue(); m_strBrkPtExpr = pArgExpr->GetValue(); m_strBrkPtExpr += GetRestOfExpressionNotSurroundedInQuotes(); CMICmnLLDBDebugSessionInfo &rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID( static_cast<lldb::break_id_t>(m_nBrkPtId)); if (brkPt.IsValid()) { brkPt.SetCondition(m_strBrkPtExpr.c_str()); CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; if (!rSessionInfo.RecordBrkPtInfoGet(m_nBrkPtId, sBrkPtInfo)) { SetError( CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_nBrkPtId)); return MIstatus::failure; } sBrkPtInfo.m_strCondition = m_strBrkPtExpr; rSessionInfo.RecordBrkPtInfo(m_nBrkPtId, sBrkPtInfo); } else { const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId)); SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), strBrkPtId.c_str())); return MIstatus::failure; } 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 CMICmdCmdBreakAfter::Execute() { CMICMDBASE_GETOPTION(pArgNumber, Number, m_constStrArgNamedNumber); CMICMDBASE_GETOPTION(pArgCount, Number, m_constStrArgNamedCount); m_nBrkPtId = pArgNumber->GetValue(); m_nBrkPtCount = pArgCount->GetValue(); CMICmnLLDBDebugSessionInfo &rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBBreakpoint brkPt = rSessionInfo.GetTarget().FindBreakpointByID( static_cast<lldb::break_id_t>(m_nBrkPtId)); if (brkPt.IsValid()) { brkPt.SetIgnoreCount(m_nBrkPtCount); CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; if (!rSessionInfo.RecordBrkPtInfoGet(m_nBrkPtId, sBrkPtInfo)) { SetError( CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INFO_OBJ_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_nBrkPtId)); return MIstatus::failure; } sBrkPtInfo.m_nIgnore = m_nBrkPtCount; rSessionInfo.RecordBrkPtInfo(m_nBrkPtId, sBrkPtInfo); } else { const CMIUtilString strBrkPtId(CMIUtilString::Format("%d", m_nBrkPtId)); SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), strBrkPtId.c_str())); return MIstatus::failure; } 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 CMICmdCmdBreakDelete::Execute() { CMICMDBASE_GETOPTION(pArgBrkPt, ListOfN, m_constStrArgNamedBrkPt); // ATM we only handle one break point ID MIuint64 nBrk = UINT64_MAX; if (!pArgBrkPt->GetExpectedOption<CMICmdArgValNumber, MIuint64>(nBrk)) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), m_constStrArgNamedBrkPt.c_str())); return MIstatus::failure; } CMICmnLLDBDebugSessionInfo &rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance()); const bool bBrkPt = rSessionInfo.GetTarget().BreakpointDelete( static_cast<lldb::break_id_t>(nBrk)); if (!bBrkPt) { const CMIUtilString strBrkNum(CMIUtilString::Format("%d", nBrk)); SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_INVALID), m_cmdData.strMiCmd.c_str(), strBrkNum.c_str())); return MIstatus::failure; } return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: Examine the string and determine if it is a valid file name path. // Type: Method. // Args: vrFileNamePath - (R) File's name and directory path. // Return: bool - True = yes valid file path, false = no. // Throws: None. //-- bool CMICmdArgValFile::IsFilePath( const CMIUtilString & vrFileNamePath ) const { const bool bHavePosSlash = (vrFileNamePath.find_first_of( "/" ) != std::string::npos); const bool bHaveBckSlash = (vrFileNamePath.find_first_of( "\\" ) != std::string::npos); // Look for --someLongOption MIint nPos = vrFileNamePath.find_first_of( "--" ); const bool bLong = (nPos == 0); if( bLong ) return false; // Look for -f type short parameters nPos = vrFileNamePath.find_first_of( "-" ); const bool bShort = (nPos == 0); if( bShort ) return false; // Look for i1 i2 i3.... nPos = vrFileNamePath.find_first_of( "i" ); const bool bFoundI1 = ((nPos == 0) && (::isdigit( vrFileNamePath[ 1 ] )) ); if( bFoundI1 ) return false; const bool bValidChars = CMIUtilString::IsAllValidAlphaAndNumeric( *vrFileNamePath.c_str() ); if( bValidChars || bHavePosSlash || bHaveBckSlash ) return true; return false; }
//++ //------------------------------------------------------------------------------------ // Details: Build the MI value result string. // Type: Method. // Args: vrVariable - (R) MI value's name. // vrValue - (R) The MI value. // Return: None. // Throws: None. //-- void CMICmnMIValueResult::BuildResult(const CMIUtilString &vVariable, const CMICmnMIValue &vValue) { const char *pFormat = m_bUseSpacing ? "%s, %s %s %s" : "%s,%s%s%s"; m_strValue = CMIUtilString::Format( pFormat, m_strValue.c_str(), vVariable.c_str(), ms_constStrEqual.c_str(), vValue.GetString().c_str()); }
//++ ------------------------------------------------------------------------------------ // 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: Release resources for *this Stdin stream. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnStreamStdinLinux::Shutdown( void ) { if( !m_bInitialized ) return MIstatus::success; m_bInitialized = false; ClrErrorDescription(); bool bOk = MIstatus::success; CMIUtilString errMsg; // Tidy up if( m_pCmdBuffer != nullptr ) { delete [] m_pCmdBuffer; m_pCmdBuffer = nullptr; } m_pStdin = nullptr; // Note shutdown order is important here MI::ModuleShutdown< CMICmnResources >( IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg ); MI::ModuleShutdown< CMICmnLog > ( IDS_MI_INIT_ERR_LOG , bOk, errMsg ); if( !bOk ) { SetErrorDescriptionn( MIRSRC( IDS_MI_SHTDWN_ERR_OS_STDIN_HANDLER ), errMsg.c_str() ); } 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 - Function succeeded. // MIstatus::failure - Function failed. // Throws: None. //-- bool CMICmdCmdExecArguments::Execute() { CMICMDBASE_GETOPTION(pArgArguments, ListOfN, m_constStrArgArguments); CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBTarget sbTarget = rSessionInfo.GetTarget(); if (!sbTarget.IsValid()) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_CURRENT), m_cmdData.strMiCmd.c_str())); return MIstatus::failure; } lldb::SBLaunchInfo sbLaunchInfo = sbTarget.GetLaunchInfo(); sbLaunchInfo.SetArguments(NULL, false); CMIUtilString strArg; size_t nArgIndex = 0; while (pArgArguments->GetExpectedOption<CMICmdArgValString, CMIUtilString>(strArg, nArgIndex)) { const char *argv[2] = { strArg.c_str(), NULL }; sbLaunchInfo.SetArguments(argv, true); ++nArgIndex; } sbTarget.SetLaunchInfo(sbLaunchInfo); return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: Build the MI value result string. // Type: Method. // Args: vrVariable - (R) MI value's name. // vrValue - (R) The MI value. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnMIValueResult::BuildResult( const CMIUtilString & vVariable, const CMICmnMIValue & vValue ) { const MIchar * pFormat = m_bUseSpacing ? "%s, %s %s %s" : "%s,%s%s%s"; m_strValue = CMIUtilString::Format( pFormat, m_strValue.c_str(), vVariable.c_str(), ms_constStrEqual.c_str(), vValue.GetString().c_str() ); return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: Work function. Client (the driver's user) is able to append their own message // in to the MI's Log trace file. // Type: Method. // Args: vMessage - (R) Client's text message. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMIDriver::WriteMessageToLog(const CMIUtilString &vMessage) { CMIUtilString msg; msg = CMIUtilString::Format(MIRSRC(IDS_MI_CLIENT_MSG), vMessage.c_str()); return m_pLog->Write(msg, CMICmnLog::eLogVerbosity_ClientMsg); }
//++ ------------------------------------------------------------------------------------ // 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: Release resources for *this thread manager. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnThreadMgrStd::Shutdown() { if (--m_clientUsageRefCnt > 0) return MIstatus::success; if (!m_bInitialized) return MIstatus::success; m_bInitialized = false; ClrErrorDescription(); bool bOk = MIstatus::success; CMIUtilString errMsg; // Tidy up ThreadAllTerminate(); // Note shutdown order is important here MI::ModuleShutdown<CMICmnResources>(IDE_MI_SHTDWN_ERR_RESOURCES, bOk, errMsg); MI::ModuleShutdown<CMICmnLog>(IDS_MI_SHTDWN_ERR_LOG, bOk, errMsg); if (!bOk) { SetErrorDescriptionn(MIRSRC(IDS_MI_SHUTDOWN_ERR), errMsg.c_str()); } return bOk; }
//++ ------------------------------------------------------------------------------------ // Details: Unbind detach or release resources used by *this driver. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMIDriver::Shutdown(void) { if (--m_clientUsageRefCnt > 0) return MIstatus::success; if (!m_bInitialized) return MIstatus::success; m_eCurrentDriverState = eDriverState_ShuttingDown; ClrErrorDescription(); bool bOk = MIstatus::success; CMIUtilString errMsg; // Shutdown all of the modules we depend on MI::ModuleShutdown<CMICmnLLDBDebugger>(IDS_MI_INIT_ERR_LLDBDEBUGGER, bOk, errMsg); MI::ModuleShutdown<CMICmdMgr>(IDS_MI_INIT_ERR_CMDMGR, bOk, errMsg); MI::ModuleShutdown<CMICmnStreamStdin>(IDS_MI_INIT_ERR_STREAMSTDIN, bOk, errMsg); MI::ModuleShutdown<CMICmnThreadMgrStd>(IDS_MI_INIT_ERR_THREADMANAGER, bOk, errMsg); MI::ModuleShutdown<CMICmnResources>(IDS_MI_INIT_ERR_RESOURCES, bOk, errMsg); MI::ModuleShutdown<CMICmnStreamStderr>(IDS_MI_INIT_ERR_STREAMSTDERR, bOk, errMsg); MI::ModuleShutdown<CMICmnStreamStdout>(IDS_MI_INIT_ERR_STREAMSTDOUT, bOk, errMsg); MI::ModuleShutdown<CMICmnLog>(IDS_MI_INIT_ERR_LOG, bOk, errMsg); if (!bOk) { SetErrorDescriptionn(MIRSRC(IDS_MI_SHUTDOWN_ERR), errMsg.c_str()); } m_eCurrentDriverState = eDriverState_NotRunning; 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; }
@@ -509,7 +509,7 @@ bool CMIDriver::StartWorkerThreads() { const CMIUtilString errMsg = CMIUtilString::Format( MIRSRC(IDS_THREADMGR_ERR_THREAD_FAIL_CREATE), CMICmnThreadMgrStd::Instance().GetErrorDescription().c_str()); - SetErrorDescriptionn(errMsg); + SetErrorDescriptionn(errMsg.c_str()); return MIstatus::failure; }
//++ //------------------------------------------------------------------------------------ // Details: Show a dialog to the process/application halts. It gives the // opportunity to // attach a debugger. // Type: Static method. // Args: None. // Return: None. // Throws: None. //-- void CMIUtilDebug::ShowDlgWaitForDbgAttach() { const CMIUtilString strCaption(CMIDriver::Instance().GetAppNameShort()); #ifdef _WIN32 ::MessageBoxA(NULL, "Attach your debugger now", strCaption.c_str(), MB_OK); #else // ToDo: Implement other platform version of an Ok to continue dialog box #endif // _WIN32 }
//++ ------------------------------------------------------------------------------------ // 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: Carry out work to complete the request to prepare and send back information // asked for. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdGdbInfo::PrintFnSharedLibrary(void) { CMICmnStreamStdout &rStdout = CMICmnStreamStdout::Instance(); bool bOk = rStdout.TextToStdout("~\"From To Syms Read Shared Object Library\""); CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBTarget sbTarget = rSessionInfo.GetTarget(); const MIuint nModules = sbTarget.GetNumModules(); for (MIuint i = 0; bOk && (i < nModules); i++) { lldb::SBModule module = sbTarget.GetModuleAtIndex(i); if (module.IsValid()) { const CMIUtilString strModuleFilePath(module.GetFileSpec().GetDirectory()); const CMIUtilString strModuleFileName(module.GetFileSpec().GetFilename()); const CMIUtilString strModuleFullPath(CMIUtilString::Format("%s/%s", strModuleFilePath.c_str(), strModuleFileName.c_str())); const CMIUtilString strHasSymbols = (module.GetNumSymbols() > 0) ? "Yes" : "No"; lldb::addr_t addrLoadS = 0xffffffff; lldb::addr_t addrLoadSize = 0; bool bHaveAddrLoad = false; const MIuint nSections = module.GetNumSections(); for (MIuint j = 0; j < nSections; j++) { lldb::SBSection section = module.GetSectionAtIndex(j); lldb::addr_t addrLoad = section.GetLoadAddress(sbTarget); if (addrLoad != (lldb::addr_t) - 1) { if (!bHaveAddrLoad) { bHaveAddrLoad = true; addrLoadS = addrLoad; } addrLoadSize += section.GetByteSize(); } } bOk = bOk && rStdout.TextToStdout(CMIUtilString::Format("~\"0x%08x\t0x%08x\t%s\t\t%s\"", addrLoadS, addrLoadS + addrLoadSize, strHasSymbols.c_str(), strModuleFullPath.c_str())); } } return bOk; }