//++ ------------------------------------------------------------------------------------ // 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: -target-attach file // Ref: http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Target-Manipulation.html#GDB_002fMI-Target-Manipulation // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdTargetDetach::Execute() { CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBProcess process = rSessionInfo.GetProcess(); if (!process.IsValid()) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str())); return MIstatus::failure; } process.Detach(); return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // 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; }
//++ ------------------------------------------------------------------------------------ // 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 CMICmdCmdStackInfoDepth::Execute( void ) { CMICMDBASE_GETOPTION( pArgThread, OptionLong, m_constStrArgThread ); CMICMDBASE_GETOPTION( pArgMaxDepth, Number, m_constStrArgMaxDepth ); // Retrieve the --thread option's thread ID (only 1) MIuint64 nThreadId = UINT64_MAX; 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; } CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); m_nThreadFrames = rSessionInfo.m_lldbProcess.GetThreadByIndexID( nThreadId ).GetNumFrames(); 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 CMICmdCmdStackInfoFrame::Execute(void) { CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); if (!sbProcess.IsValid()) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str())); return MIstatus::failure; } lldb::SBThread sbThread = sbProcess.GetSelectedThread(); MIuint nFrameId = sbThread.GetSelectedFrame().GetFrameID(); if (!rSessionInfo.MIResponseFormFrameInfo(sbThread, nFrameId, m_miValueTuple)) 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 - Function succeeded. // MIstatus::failure - Function failed. // Throws: None. //-- bool CMICmdCmdStackSelectFrame::Execute(void) { CMICMDBASE_GETOPTION(pArgFrame, Number, m_constStrArgFrame); CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBThread sbThread = rSessionInfo.GetProcess().GetSelectedThread(); const MIuint nFrameId = pArgFrame->GetValue(); m_bFrameInvalid = (nFrameId >= sbThread.GetNumFrames()); if (m_bFrameInvalid) return MIstatus::success; lldb::SBFrame sbFrame = sbThread.SetSelectedFrame(nFrameId); m_bFrameInvalid = !sbFrame.IsValid(); 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( pArgPrintValues, Number, m_constStrArgPrintValues ); // 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; } } CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess; lldb::SBThread thread; if( nThreadId == UINT64_MAX ) thread = rProcess.GetSelectedThread(); else thread = rProcess.GetThreadByIndexID( nThreadId ); 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; } lldb::SBFrame frame = thread.GetFrameAtIndex( 0 ); CMICmnMIValueList miValueList( true ); const MIuint vMaskVarTypes = 0x0100; if( !rSessionInfo.MIResponseFormVariableInfo( frame, vMaskVarTypes, miValueList ) ) return MIstatus::failure; m_miValueList = miValueList; 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 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: 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 CMICmdCmdExecAbort::Execute() { CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); if (!sbProcess.IsValid()) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str())); return MIstatus::failure; } lldb::SBError sbError = sbProcess.Destroy(); if (sbError.Fail()) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_LLDBPROCESS_DESTROY), m_cmdData.strMiCmd.c_str(), sbError.GetCString())); 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 CMICmdCmdBreakInsert::Acknowledge() { // Get breakpoint information CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; if (!rSessionInfo.RecordBrkPtInfoGet(m_brkPt.GetID(), sBrkPtInfo)) return MIstatus::failure; // MI print // "^done,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016" PRIx64 "\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",thread-groups=[\"%s\"],times=\"%d\",original-location=\"%s\"}" CMICmnMIValueTuple miValueTuple; if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple)) return MIstatus::failure; const CMICmnMIValueResult miValueResultD("bkpt", miValueTuple); const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResultD); m_miResultRecord = miRecordResult; return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: The invoker requires this function. The command prepares a MI Record Result // for the work carried out in the Execute(). // Called only if Execute() set status as successful on completion. // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdExecRun::Acknowledge() { const CMICmnMIResultRecord miRecordResult(m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Running); m_miResultRecord = miRecordResult; CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); lldb::pid_t pid = rSessionInfo.GetProcess().GetProcessID(); // Give the client '=thread-group-started,id="i1" pid="xyz"' m_bHasResultRecordExtra = true; const CMICmnMIValueConst miValueConst2("i1"); const CMICmnMIValueResult miValueResult2("id", miValueConst2); const CMIUtilString strPid(CMIUtilString::Format("%lld", pid)); const CMICmnMIValueConst miValueConst(strPid); const CMICmnMIValueResult miValueResult("pid", miValueConst); CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, miValueResult2); miOutOfBand.Add(miValueResult); m_miResultRecordExtra = miOutOfBand.GetString(); 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 CMICmdCmdTargetSelect::Acknowledge( void ) { const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Connected ); m_miResultRecord = miRecordResult; CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); lldb::pid_t pid = rSessionInfo.m_lldbProcess.GetProcessID(); // Prod the client i.e. Eclipse with out-of-band results to help it 'continue' because it is using LLDB debugger // Give the client '=thread-group-started,id="i1"' m_bHasResultRecordExtra = true; const CMICmnMIValueConst miValueConst2( "i1" ); const CMICmnMIValueResult miValueResult2( "id", miValueConst2 ); const CMIUtilString strPid( CMIUtilString::Format( "%lld", pid ) ); const CMICmnMIValueConst miValueConst( strPid ); const CMICmnMIValueResult miValueResult( "pid", miValueConst ); CMICmnMIOutOfBandRecord miOutOfBand( CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, miValueResult2 ); miOutOfBand.Add( miValueResult ); m_miResultRecordExtra = miOutOfBand.GetString(); 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 CMICmdCmdExecFinish::Execute() { CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); // Retrieve the --thread option's thread ID (only 1) MIuint64 nThreadId = UINT64_MAX; if (pArgThread->GetFound() && !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; } CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBDebugger &rDebugger = rSessionInfo.GetDebugger(); CMIUtilString strCmd("thread step-out"); if (nThreadId != UINT64_MAX) strCmd += CMIUtilString::Format(" %llu", nThreadId); rDebugger.GetCommandInterpreter().HandleCommand(strCmd.c_str(), m_lldbResult, false); 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 CMICmdCmdBreakInsert::Acknowledge( void ) { // Get breakpoint information CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; if( !rSessionInfo.GetBrkPtInfo( m_brkPt, sBrkPtInfo ) ) { return MIstatus::failure; } // CODETAG_LLDB_BREAKPOINT_CREATION // Add more breakpoint information or overwrite existing information sBrkPtInfo.m_bDisp = m_bBrkPtIsTemp; sBrkPtInfo.m_bEnabled = m_bBrkPtEnabled; sBrkPtInfo.m_bHaveArgOptionThreadGrp = m_bHaveArgOptionThreadGrp; sBrkPtInfo.m_strOptThrdGrp = m_strArgOptionThreadGrp; sBrkPtInfo.m_nTimes = m_brkPt.GetNumLocations(); 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; // MI print "^done,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\",func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",thread-groups=[\"%s\"],times=\"%d\",original-location=\"%s\"}" CMICmnMIValueTuple miValueTuple; if( !rSessionInfo.MIResponseFormBrkPtInfo( sBrkPtInfo, miValueTuple ) ) { return MIstatus::failure; } const CMICmnMIValueResult miValueResultD( "bkpt", miValueTuple ); const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResultD ); m_miResultRecord = miRecordResult; return MIstatus::success; }
//++ //------------------------------------------------------------------------------------ // Details: Retrieve from the LLDB SB Value object the value of the variable // described in // text. If the value is invalid (or the SBValue object invalid) then // "??" is // returned. // Type: Method. // Args: None. // Return: CMIUtilString - Text description of the variable's value or "??". // Throws: None. //-- CMIUtilString CMICmnLLDBUtilSBValue::GetValue( const bool vbExpandAggregates /* = false */) const { if (!m_bValidSBValue) return m_pUnkwn; CMICmnLLDBDebugSessionInfo &rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance()); bool bPrintExpandAggregates = false; bPrintExpandAggregates = rSessionInfo.SharedDataRetrieve<bool>( rSessionInfo.m_constStrPrintExpandAggregates, bPrintExpandAggregates) && bPrintExpandAggregates; const bool bHandleArrayTypeAsSimple = m_bHandleArrayType && !vbExpandAggregates && !bPrintExpandAggregates; CMIUtilString value; const bool bIsSimpleValue = GetSimpleValue(bHandleArrayTypeAsSimple, value); if (bIsSimpleValue) return value; if (!vbExpandAggregates && !bPrintExpandAggregates) return m_pComposite; bool bPrintAggregateFieldNames = false; bPrintAggregateFieldNames = !rSessionInfo.SharedDataRetrieve<bool>( rSessionInfo.m_constStrPrintAggregateFieldNames, bPrintAggregateFieldNames) || bPrintAggregateFieldNames; CMICmnMIValueTuple miValueTuple; const bool bOk = GetCompositeValue(bPrintAggregateFieldNames, miValueTuple); if (!bOk) return m_pUnkwn; value = miValueTuple.GetString(); return value; }
//++ ------------------------------------------------------------------------------------ // 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 CMICmdCmdBreakEnable::Execute( void ) { 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() ); lldb::SBBreakpoint brkPt = rSessionInfo.m_lldbTarget.FindBreakpointByID( static_cast< lldb::break_id_t >( nBrk ) ); if( brkPt.IsValid() ) { m_bBrkPtEnabledOk = true; brkPt.SetEnabled( false ); m_nBrkPtId = nBrk; } 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 CMICmdCmdExecRun::Execute() { CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBError error; lldb::SBStream errMsg; lldb::SBLaunchInfo launchInfo = rSessionInfo.GetTarget().GetLaunchInfo(); launchInfo.SetListener(rSessionInfo.GetListener()); lldb::SBProcess process = rSessionInfo.GetTarget().Launch(launchInfo, error); if ((!process.IsValid()) || (error.Fail())) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PROCESS), m_cmdData.strMiCmd.c_str(), errMsg.GetData())); return MIstatus::failure; } 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; } 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( void ) { 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.m_lldbTarget.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: Retrieve from the LLDB SB Value object the value of the variable // described in // text if it has a simple format (not composite). // Type: Method. // Args: vwrValue - (W) The SBValue in a string format. // Return: MIstatus::success - Function succeeded. // MIstatus::failure - Function failed. // Throws: None. //-- bool CMICmnLLDBUtilSBValue::GetSimpleValue(const bool vbHandleArrayType, CMIUtilString &vwrValue) const { const MIuint nChildren = m_rValue.GetNumChildren(); if (nChildren == 0) { vwrValue = GetValueSummary(!m_bHandleCharType && IsCharType(), m_pUnkwn); return MIstatus::success; } else if (IsPointerType()) { vwrValue = GetValueSummary(!m_bHandleCharType && IsPointeeCharType(), m_pUnkwn); return MIstatus::success; } else if (IsArrayType()) { CMICmnLLDBDebugSessionInfo &rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance()); bool bPrintCharArrayAsString = false; bPrintCharArrayAsString = rSessionInfo.SharedDataRetrieve<bool>( rSessionInfo.m_constStrPrintCharArrayAsString, bPrintCharArrayAsString) && bPrintCharArrayAsString; if (bPrintCharArrayAsString && m_bHandleCharType && IsFirstChildCharType()) { vwrValue = GetValueSummary(false); return MIstatus::success; } else if (vbHandleArrayType) { vwrValue = CMIUtilString::Format("[%u]", nChildren); return MIstatus::success; } } else { // Treat composite value which has registered summary // (for example with AddCXXSummary) as simple value vwrValue = GetValueSummary(false); if (!vwrValue.empty()) return MIstatus::success; } // Composite variable type i.e. struct return MIstatus::failure; }
//++ ------------------------------------------------------------------------------------ // 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: 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 CMICmdCmdListThreadGroups::Acknowledge( void ) { if( m_bHaveArgOption ) { if( m_bHaveArgRecurse ) { const CMICmnMIValueConst miValueConst( MIRSRC( IDS_WORD_NOT_IMPLEMENTED_BRKTS ) ); const CMICmnMIValueResult miValueResult( "msg", miValueConst ); const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); m_miResultRecord = miRecordResult; return MIstatus::success; } const CMICmnMIValueConst miValueConst1( "i1" ); const CMICmnMIValueResult miValueResult1( "id", miValueConst1 ); CMICmnMIValueTuple miTuple( miValueResult1 ); const CMICmnMIValueConst miValueConst2( "process" ); const CMICmnMIValueResult miValueResult2( "type", miValueConst2 ); miTuple.Add( miValueResult2 ); CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); const lldb::pid_t pid = rSessionInfo.m_lldbProcess.GetProcessID(); const CMIUtilString strPid( CMIUtilString::Format( "%lld", pid ) ); const CMICmnMIValueConst miValueConst3( strPid ); const CMICmnMIValueResult miValueResult3( "pid", miValueConst3 ); miTuple.Add( miValueResult3 ); const CMICmnMIValueConst miValueConst4( MIRSRC( IDS_WORD_NOT_IMPLEMENTED_BRKTS ) ); const CMICmnMIValueResult miValueResult4( "num_children", miValueConst4 ); miTuple.Add( miValueResult4 ); const CMICmnMIValueConst miValueConst5( MIRSRC( IDS_WORD_NOT_IMPLEMENTED_BRKTS ) ); const CMICmnMIValueResult miValueResult5( "cores", miValueConst5 ); miTuple.Add( miValueResult5 ); const CMICmnMIValueList miValueList( miTuple ); const CMICmnMIValueResult miValueResult6( "groups", miValueList ); const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult6 ); m_miResultRecord = miRecordResult; return MIstatus::success; } if( !m_bIsI1 ) { const CMICmnMIValueConst miValueConst1( "i1" ); const CMICmnMIValueResult miValueResult1( "id", miValueConst1 ); CMICmnMIValueTuple miTuple( miValueResult1 ); const CMICmnMIValueConst miValueConst2( "process" ); const CMICmnMIValueResult miValueResult2( "type", miValueConst2 ); miTuple.Add( miValueResult2 ); CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); const lldb::pid_t pid = rSessionInfo.m_lldbProcess.GetProcessID(); const CMIUtilString strPid( CMIUtilString::Format( "%lld", pid ) ); const CMICmnMIValueConst miValueConst3( strPid ); const CMICmnMIValueResult miValueResult3( "pid", miValueConst3 ); miTuple.Add( miValueResult3 ); lldb::SBTarget & rTrgt = rSessionInfo.m_lldbTarget; const MIchar * pDir = rTrgt.GetExecutable().GetDirectory(); const MIchar * pFileName = rTrgt.GetExecutable().GetFilename(); const CMIUtilString strFile( CMIUtilString::Format( "%s/%s", pDir, pFileName ) ); const CMICmnMIValueConst miValueConst4( strFile ); const CMICmnMIValueResult miValueResult4( "executable", miValueConst4 ); miTuple.Add( miValueResult4 ); const CMICmnMIValueList miValueList( miTuple ); const CMICmnMIValueResult miValueResult5( "groups", miValueList ); const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult5 ); m_miResultRecord = miRecordResult; return MIstatus::success; } // Build up a list of thread information from tuples VecMIValueTuple_t::const_iterator it = m_vecMIValueTuple.begin(); if( it == m_vecMIValueTuple.end() ) { const CMICmnMIValueConst miValueConst( "[]" ); const CMICmnMIValueResult miValueResult( "threads", miValueConst ); const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); m_miResultRecord = miRecordResult; return MIstatus::success; } CMICmnMIValueList miValueList( *it ); ++it; while( it != m_vecMIValueTuple.end() ) { const CMICmnMIValueTuple & rTuple( *it ); miValueList.Add( rTuple ); // Next ++it; } const CMICmnMIValueResult miValueResult( "threads", miValueList ); const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); m_miResultRecord = miRecordResult; return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: 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 CMICmdCmdStackListArguments::Execute() { CMICMDBASE_GETOPTION(pArgThread, OptionLong, m_constStrArgThread); CMICMDBASE_GETOPTION(pArgPrintValues, PrintValues, m_constStrArgPrintValues); CMICMDBASE_GETOPTION(pArgFrameLow, Number, m_constStrArgFrameLow); CMICMDBASE_GETOPTION(pArgFrameHigh, Number, m_constStrArgFrameHigh); // 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; } } const CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e eVarInfoFormat = static_cast<CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e>(pArgPrintValues->GetValue()); MIuint nFrameLow = 0; MIuint nFrameHigh = UINT32_MAX; if (pArgFrameLow->GetFound() && pArgFrameHigh->GetFound()) { nFrameLow = pArgFrameLow->GetValue(); nFrameHigh = pArgFrameHigh->GetValue() + 1; } else if (pArgFrameLow->GetFound() || pArgFrameHigh->GetFound()) { // Only low-frame or high-frame was specified but both are required SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_FRAME_RANGE_INVALID), m_cmdData.strMiCmd.c_str())); return MIstatus::failure; } CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); lldb::SBThread thread = (nThreadId != UINT64_MAX) ? sbProcess.GetThreadByIndexID(nThreadId) : sbProcess.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(); if (nFrameLow >= nFrames) { // The low-frame is larger than the actual number of frames SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_THREAD_FRAME_RANGE_INVALID), m_cmdData.strMiCmd.c_str())); return MIstatus::failure; } nFrameHigh = std::min(nFrameHigh, nFrames); for (MIuint i = nFrameLow; i < nFrameHigh; i++) { lldb::SBFrame frame = thread.GetFrameAtIndex(i); CMICmnMIValueList miValueList(true); const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Arguments; if (!rSessionInfo.MIResponseFormVariableInfo(frame, maskVarTypes, eVarInfoFormat, miValueList)) return MIstatus::failure; const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", i)); const CMICmnMIValueResult miValueResult("level", miValueConst); CMICmnMIValueTuple miValueTuple(miValueResult); const CMICmnMIValueResult miValueResult2("args", miValueList); miValueTuple.Add(miValueResult2); const CMICmnMIValueResult miValueResult3("frame", miValueTuple); m_miValueList.Add(miValueResult3); } 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); CMICMDBASE_GETOPTION(pArgPrintValues, Number, m_constStrArgPrintValues); CMICMDBASE_GETOPTION(pArgNoValues, OptionLong, m_constStrArgNoValues); CMICMDBASE_GETOPTION(pArgAllValues, OptionLong, m_constStrArgAllValues); CMICMDBASE_GETOPTION(pArgSimpleValues, OptionLong, m_constStrArgSimpleValues); // 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::VariableInfoFormat_e eVarInfoFormat; if (pArgPrintValues->GetFound()) { const MIuint nPrintValues = pArgPrintValues->GetValue(); if (nPrintValues >= CMICmnLLDBDebugSessionInfo::kNumVariableInfoFormats) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PRINT_VALUES), m_cmdData.strMiCmd.c_str())); return MIstatus::failure; } eVarInfoFormat = static_cast<CMICmnLLDBDebugSessionInfo::VariableInfoFormat_e>(nPrintValues); } else if (pArgNoValues->GetFound()) eVarInfoFormat = CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_NoValues; else if (pArgAllValues->GetFound()) eVarInfoFormat = CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_AllValues; else if (pArgSimpleValues->GetFound()) eVarInfoFormat = CMICmnLLDBDebugSessionInfo::eVariableInfoFormat_SimpleValues; else { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_PRINT_VALUES), m_cmdData.strMiCmd.c_str())); return MIstatus::failure; } CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); lldb::SBProcess sbProcess = rSessionInfo.GetProcess(); lldb::SBThread thread = (nThreadId != UINT64_MAX) ? sbProcess.GetThreadByIndexID(nThreadId) : sbProcess.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; } lldb::SBFrame frame = (nFrame != UINT64_MAX) ? thread.GetFrameAtIndex(nFrame) : thread.GetSelectedFrame(); CMICmnMIValueList miValueList(true); const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Locals; if (!rSessionInfo.MIResponseFormVariableInfo(frame, maskVarTypes, eVarInfoFormat, miValueList)) return MIstatus::failure; m_miValueList = miValueList; 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. // Synopis: -list-thread-groups [ --available ] [ --recurse 1 ] [ group ... ] // This command does not follow the MI documentation exactly. Has an extra // argument "i1" to handle. // Ref: http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Miscellaneous-Commands.html#GDB_002fMI-Miscellaneous-Commands // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdListThreadGroups::Execute( void ) { if( m_setCmdArgs.IsArgContextEmpty() ) // No options so "top level thread groups" return MIstatus::success; CMICMDBASE_GETOPTION( pArgAvailable, OptionLong, m_constStrArgNamedAvailable ); CMICMDBASE_GETOPTION( pArgRecurse, OptionLong, m_constStrArgNamedRecurse ); CMICMDBASE_GETOPTION( pArgGroup, ListOfN, m_constStrArgNamedGroup ); CMICMDBASE_GETOPTION( pArgThreadGroup, ThreadGrp, m_constStrArgNamedThreadGroup ); // Demo of how to get the value of long argument --recurse's option of 1 "--recurse 1" const CMICmdArgValOptionLong::VecArgObjPtr_t & rVecOptions( pArgRecurse->GetExpectedOptions() ); const CMICmdArgValNumber * pRecurseDepthOption = (rVecOptions.size() > 0) ? static_cast< CMICmdArgValNumber * >( rVecOptions[ 1 ] ) : nullptr; const MIuint nRecurseDepth = (pRecurseDepthOption != nullptr) ? pRecurseDepthOption->GetValue() : 0; // Demo of how to get List of N numbers (the Group argument not implement for this command (yet)) const CMICmdArgValListOfN::VecArgObjPtr_t & rVecGroupId( pArgGroup->GetValue() ); CMICmdArgValListOfN::VecArgObjPtr_t::const_iterator it = rVecGroupId.begin(); while( it != rVecGroupId.end() ) { const CMICmdArgValNumber * pOption = static_cast< CMICmdArgValNumber * >( *it ); const MIuint nGrpId = pOption->GetValue(); // Next ++it; } // Got some options so "threads" if( pArgAvailable->GetFound() ) { if( pArgRecurse->GetFound() ) { m_bHaveArgRecurse = true; return MIstatus::success; } m_bHaveArgOption = true; return MIstatus::success; } // "i1" as first argument (pos 0 of possible arg) if( !pArgThreadGroup->GetFound() ) return MIstatus::success; m_bIsI1 = true; CMICmnLLDBDebugSessionInfo & rSessionInfo( CMICmnLLDBDebugSessionInfo::Instance() ); lldb::SBProcess & rProcess = rSessionInfo.m_lldbProcess; // Note do not check for rProcess is IsValid(), continue m_vecMIValueTuple.clear(); const MIuint nThreads = rProcess.GetNumThreads(); for( MIuint i = 0; i < nThreads; i++ ) { // GetThreadAtIndex() uses a base 0 index // GetThreadByIndexID() uses a base 1 index lldb::SBThread thread = rProcess.GetThreadAtIndex( i ); if( thread.IsValid() ) { CMICmnMIValueTuple miTuple; if( !rSessionInfo.MIResponseFormThreadInfo( m_cmdData, thread, miTuple ) ) return MIstatus::failure; m_vecMIValueTuple.push_back( miTuple ); } } 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; }
//++ ------------------------------------------------------------------------------------ // 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: -target-select type parameters ... // Ref: http://sourceware.org/gdb/onlinedocs/gdb/GDB_002fMI-Target-Manipulation.html#GDB_002fMI-Target-Manipulation // Type: Overridden. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmdCmdTargetSelect::Execute(void) { CMICMDBASE_GETOPTION(pArgType, String, m_constStrArgNamedType); CMICMDBASE_GETOPTION(pArgParameters, String, m_constStrArgNamedParameters); CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance()); // Check we have a valid target // Note: target created via 'file-exec-and-symbols' command if (!rSessionInfo.GetTarget().IsValid()) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_CURRENT), m_cmdData.strMiCmd.c_str())); return MIstatus::failure; } // Verify that we are executing remotely const CMIUtilString &rRemoteType(pArgType->GetValue()); if (rRemoteType != "remote") { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_TYPE), m_cmdData.strMiCmd.c_str(), rRemoteType.c_str())); return MIstatus::failure; } // Create a URL pointing to the remote gdb stub const CMIUtilString strUrl = CMIUtilString::Format("connect://%s", pArgParameters->GetValue().c_str()); // Ask LLDB to collect to the target port const MIchar *pPlugin("gdb-remote"); lldb::SBError error; lldb::SBProcess process = rSessionInfo.GetTarget().ConnectRemote(rSessionInfo.GetListener(), strUrl.c_str(), pPlugin, error); // Verify that we have managed to connect successfully lldb::SBStream errMsg; if (!process.IsValid()) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_INVALID_TARGET_PLUGIN), m_cmdData.strMiCmd.c_str(), errMsg.GetData())); return MIstatus::failure; } if (error.Fail()) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_CONNECT_TO_TARGET), m_cmdData.strMiCmd.c_str(), errMsg.GetData())); return MIstatus::failure; } // Set the environment path if we were given one CMIUtilString strWkDir; if (rSessionInfo.SharedDataRetrieve<CMIUtilString>(rSessionInfo.m_constStrSharedDataKeyWkDir, strWkDir)) { lldb::SBDebugger &rDbgr = rSessionInfo.GetDebugger(); if (!rDbgr.SetCurrentPlatformSDKRoot(strWkDir.c_str())) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FNFAILED), m_cmdData.strMiCmd.c_str(), "target-select")); return MIstatus::failure; } } // Set the shared object path if we were given one CMIUtilString strSolibPath; if (rSessionInfo.SharedDataRetrieve<CMIUtilString>(rSessionInfo.m_constStrSharedDataSolibPath, strSolibPath)) { lldb::SBDebugger &rDbgr = rSessionInfo.GetDebugger(); lldb::SBCommandInterpreter cmdIterpreter = rDbgr.GetCommandInterpreter(); CMIUtilString strCmdString = CMIUtilString::Format("target modules search-paths add . %s", strSolibPath.c_str()); lldb::SBCommandReturnObject retObj; cmdIterpreter.HandleCommand(strCmdString.c_str(), retObj, false); if (!retObj.Succeeded()) { SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_FNFAILED), m_cmdData.strMiCmd.c_str(), "target-select")); 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() { 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; CMIUtilString fileName; MIuint nFileLine = 0; CMIUtilString strFileFn; CMIUtilString rStrLineOrFn; // Is the string in the form 'file:func' or 'file:line'? // If so, find the position of the ':' separator. const size_t nPosColon = findFileSeparatorPos(m_brkName); if (nPosColon != std::string::npos) { // Extract file name and line number from it fileName = m_brkName.substr(0, nPosColon); rStrLineOrFn = m_brkName.substr(nPosColon + 1, m_brkName.size() - nPosColon - 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 sbTarget = rSessionInfo.GetTarget(); switch (eBrkPtType) { case eBreakPoint_ByAddress: m_brkPt = sbTarget.BreakpointCreateByAddress(nAddress); break; case eBreakPoint_ByFileFn: { lldb::SBFileSpecList module; // search in all modules lldb::SBFileSpecList compUnit; compUnit.Append (lldb::SBFileSpec(fileName.c_str())); m_brkPt = sbTarget.BreakpointCreateByName(strFileFn.c_str(), module, compUnit); break; } case eBreakPoint_ByFileLine: m_brkPt = sbTarget.BreakpointCreateByLocation(fileName.c_str(), nFileLine); break; case eBreakPoint_ByName: m_brkPt = sbTarget.BreakpointCreateByName(m_brkName.c_str(), nullptr); break; case eBreakPoint_count: case eBreakPoint_NotDefineYet: case eBreakPoint_Invalid: bOk = MIstatus::failure; break; } if (bOk) { if (!m_bBrkPtIsPending && (m_brkPt.GetNumLocations() == 0)) { sbTarget.BreakpointDelete(m_brkPt.GetID()); SetError(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_LOCATION_NOT_FOUND), m_cmdData.strMiCmd.c_str(), m_brkName.c_str())); return MIstatus::failure; } 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); } // CODETAG_LLDB_BREAKPOINT_CREATION // This is in the main thread // Record break point information to be by LLDB event handler function CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo; if (!rSessionInfo.GetBrkPtInfo(m_brkPt, sBrkPtInfo)) return MIstatus::failure; 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_nTimes = m_brkPt.GetHitCount(); 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; } // CODETAG_LLDB_BRKPT_ID_MAX 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; }