//++ //------------------------------------------------------------------------------------ // Details: Carry out work to complete the GDB set option 'target-async' to // prepare // and send back information asked for. // 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 CMICmdCmdGdbSet::OptionFnTargetAsync( const CMIUtilString::VecString_t &vrWords) { bool bAsyncMode = false; bool bOk = true; if (vrWords.size() > 1) // Too many arguments. bOk = false; else if (vrWords.size() == 0) // If no arguments, default is "on". bAsyncMode = true; else if (CMIUtilString::Compare(vrWords[0], "on")) bAsyncMode = true; else if (CMIUtilString::Compare(vrWords[0], "off")) bAsyncMode = false; else // Unrecognized argument. bOk = false; if (!bOk) { // Report error. m_bGbbOptionFnHasError = true; m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSET_OPT_TARGETASYNC); return MIstatus::failure; } // Turn async mode on/off. CMICmnLLDBDebugSessionInfo &rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance()); rSessionInfo.GetDebugger().SetAsync(bAsyncMode); return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // 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: Parse the text following *this argument and extract the options the // values of // CMICmdArgValListBase::m_eArgType forming argument objects for each // of those // options extracted. // Type: Method. // Args: vrwTxt - (RW) The command's argument options string. // nArgIndex - (R) The Nth arg position in argument context from // the left. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdArgValOptionLong::ExtractExpectedOptions(CMICmdArgContext &vrwTxt, const MIuint nArgIndex) { CMIUtilString::VecString_t vecOptions = vrwTxt.GetArgs(); if (vecOptions.size() == 0) return MIstatus::failure; MIuint nArgIndexCnt = 0; MIuint nTypeCnt = 0; MIuint nTypeCnt2 = 0; MIuint nFoundNOptionsCnt = 0; CMIUtilString::VecString_t::const_iterator it = vecOptions.begin(); while (it != vecOptions.end()) { // Move to the Nth argument position from left before do validation/checking if (nArgIndexCnt++ == nArgIndex) { nTypeCnt++; const CMIUtilString &rOption(*it); if (IsExpectedCorrectType(rOption, m_eExpectingOptionType)) { nTypeCnt2++; CMICmdArgValBase *pOptionObj = CreationObj(rOption, m_eExpectingOptionType); if ((pOptionObj != nullptr) && vrwTxt.RemoveArgAtPos(rOption, nArgIndex)) { nFoundNOptionsCnt++; m_vecArgsExpected.push_back(pOptionObj); } } // Is the sequence 'options' of same type broken. Expecting the same type // until the // next argument. if (nTypeCnt != nTypeCnt2) return MIstatus::failure; if (nFoundNOptionsCnt == m_nExpectingNOptions) return MIstatus::success; } // Next ++it; } if (nFoundNOptionsCnt != m_nExpectingNOptions) return MIstatus::failure; return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: Carry out work to complete the GDB set option 'output-radix' to prepare // and send back information asked for. // Type: Method. // Args: vrWords - (R) List of additional parameters used by this option. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdGdbSet::OptionFnOutputRadix(const CMIUtilString::VecString_t &vrWords) { // Check we have at least one argument if (vrWords.size() < 1) { m_bGbbOptionFnHasError = true; m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH); return MIstatus::failure; } const CMIUtilString &rStrValOutputRadix(vrWords[0]); CMICmnLLDBDebugSessionInfoVarObj::varFormat_e format = CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid; MIint64 radix; if (rStrValOutputRadix.ExtractNumber(radix)) { switch (radix) { case 8: format = CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Octal; break; case 10: format = CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Natural; break; case 16: format = CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Hex; break; default: format = CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid; break; } } if (format == CMICmnLLDBDebugSessionInfoVarObj::eVarFormat_Invalid) { m_bGbbOptionFnHasError = false; SetError(CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_ADD), m_cmdData.strMiCmd.c_str(), "Output Radix")); return MIstatus::failure; } CMICmnLLDBDebugSessionInfoVarObj::VarObjSetFormat(format); return MIstatus::success; }
//++ //------------------------------------------------------------------------------------ // Details: Carry out work to complete the GDB set option 'disassembly-flavor' // to prepare // and send back information asked for. // Type: Method. // Args: vrWords - (R) List of additional parameters used by this option. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdGdbSet::OptionFnDisassemblyFlavor( const CMIUtilString::VecString_t &vrWords) { // Check we have at least one argument if (vrWords.size() < 1) { m_bGbbOptionFnHasError = true; // m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH); return MIstatus::failure; } const CMIUtilString &rStrValDisasmFlavor(vrWords[0]); lldb::SBDebugger &rDbgr = m_rLLDBDebugSessionInfo.GetDebugger(); lldb::SBError error = lldb::SBDebugger::SetInternalVariable( "target.x86-disassembly-flavor", rStrValDisasmFlavor.c_str(), rDbgr.GetInstanceName()); if (error.Fail()) { m_strGdbOptionFnError = error.GetCString(); return MIstatus::failure; } return MIstatus::success; }
//++ //------------------------------------------------------------------------------------ // Details: Carry out work to complete the GDB set option // 'print-char-array-as-string' to // prepare and send back information asked for. // 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 CMICmdCmdGdbSet::OptionFnPrint(const CMIUtilString::VecString_t &vrWords) { const bool bAllArgs(vrWords.size() == 2); const bool bArgOn(bAllArgs && (CMIUtilString::Compare(vrWords[1], "on") || CMIUtilString::Compare(vrWords[1], "1"))); const bool bArgOff(bAllArgs && (CMIUtilString::Compare(vrWords[1], "off") || CMIUtilString::Compare(vrWords[1], "0"))); if (!bAllArgs || (!bArgOn && !bArgOff)) { m_bGbbOptionFnHasError = true; m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSET_OPT_PRINT_BAD_ARGS); return MIstatus::failure; } const CMIUtilString strOption(vrWords[0]); CMIUtilString strOptionKey; if (CMIUtilString::Compare(strOption, "char-array-as-string")) strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintCharArrayAsString; else if (CMIUtilString::Compare(strOption, "expand-aggregates")) strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintExpandAggregates; else if (CMIUtilString::Compare(strOption, "aggregate-field-names")) strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintAggregateFieldNames; else { m_bGbbOptionFnHasError = true; m_strGdbOptionFnError = CMIUtilString::Format( MIRSRC(IDS_CMD_ERR_GDBSET_OPT_PRINT_UNKNOWN_OPTION), strOption.c_str()); return MIstatus::failure; } const bool bOptionValue(bArgOn); if (!m_rLLDBDebugSessionInfo.SharedDataAdd<bool>(strOptionKey, bOptionValue)) { m_bGbbOptionFnHasError = false; SetError(CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_ADD), m_cmdData.strMiCmd.c_str(), strOptionKey.c_str())); return MIstatus::failure; } return MIstatus::success; }
//++ //------------------------------------------------------------------------------------ // Details: Carry out work to complete the GDB show option 'print' 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::OptionFnPrint( const CMIUtilString::VecString_t &vrWords) { const bool bAllArgs(vrWords.size() == 1); if (!bAllArgs) { m_bGbbOptionFnHasError = true; m_strGdbOptionFnError = MIRSRC(IDS_CMD_ERR_GDBSHOW_OPT_PRINT_BAD_ARGS); return MIstatus::failure; } const CMIUtilString strOption(vrWords[0]); CMIUtilString strOptionKey; bool bOptionValueDefault = false; if (CMIUtilString::Compare(strOption, "char-array-as-string")) strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintCharArrayAsString; else if (CMIUtilString::Compare(strOption, "expand-aggregates")) strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintExpandAggregates; else if (CMIUtilString::Compare(strOption, "aggregate-field-names")) { strOptionKey = m_rLLDBDebugSessionInfo.m_constStrPrintAggregateFieldNames; bOptionValueDefault = true; } else { m_bGbbOptionFnHasError = true; m_strGdbOptionFnError = CMIUtilString::Format( MIRSRC(IDS_CMD_ERR_GDBSHOW_OPT_PRINT_UNKNOWN_OPTION), strOption.c_str()); return MIstatus::failure; } bool bOptionValue = false; bOptionValue = bOptionValueDefault ? !m_rLLDBDebugSessionInfo.SharedDataRetrieve<bool>( strOptionKey, bOptionValue) || bOptionValue : m_rLLDBDebugSessionInfo.SharedDataRetrieve<bool>( strOptionKey, bOptionValue) && bOptionValue; m_strValue = bOptionValue ? "on" : "off"; return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: Carry out work to complete the GDB set option 'solib-search-path' to prepare // and send back information asked for. // Type: Method. // Args: vrWords - (R) List of additional parameters used by this option. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdGdbSet::OptionFnSolibSearchPath( const CMIUtilString::VecString_t & vrWords ) { // Check we have at least one argument if( vrWords.size() < 1 ) { m_bGbbOptionFnHasError = true; m_strGdbOptionFnError = MIRSRC( IDS_CMD_ERR_GDBSET_OPT_SOLIBSEARCHPATH ); return MIstatus::failure; } const CMIUtilString & rStrValSolibPath( vrWords[ 0 ] ); // Add 'solib-search-path' to the shared data list const CMIUtilString & rStrKeySolibPath( m_rLLDBDebugSessionInfo.m_constStrSharedDataSolibPath ); if( !m_rLLDBDebugSessionInfo.SharedDataAdd< CMIUtilString >( rStrKeySolibPath, rStrValSolibPath ) ) { m_bGbbOptionFnHasError = false; SetError( CMIUtilString::Format( MIRSRC( IDS_DBGSESSION_ERR_SHARED_DATA_ADD ), m_cmdData.strMiCmd.c_str(), rStrKeySolibPath.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 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; }