//++ ------------------------------------------------------------------------------------ // Details: Form MI partial response by appending more MI value type objects to the // tuple type object past in. // Type: Method. // Args: vrThread - (R) LLDB thread object. // vwrMIValueTuple - (W) MI value tuple object. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo( const lldb::SBThread & vrThread, const MIuint vnLevel, CMICmnMIValueTuple & vwrMiValueTuple ) { lldb::SBThread & rThread = const_cast< lldb::SBThread & >( vrThread ); lldb::SBFrame frame = rThread.GetFrameAtIndex( vnLevel ); lldb::addr_t pc = 0; CMIUtilString fnName; CMIUtilString fileName; CMIUtilString path; MIuint nLine = 0; if( !GetFrameInfo( frame, pc, fnName, fileName, path, nLine ) ) return MIstatus::failure; CMICmnMIValueList miValueList( true ); const MIuint vMaskVarTypes = 0x1000; if( !MIResponseFormVariableInfo( frame, vMaskVarTypes, miValueList ) ) return MIstatus::failure; // MI print "{level=\"0\",addr=\"0x%08llx\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"}" const CMIUtilString strLevel( CMIUtilString::Format( "%d", vnLevel ) ); const CMICmnMIValueConst miValueConst( strLevel ); const CMICmnMIValueResult miValueResult( "level", miValueConst ); CMICmnMIValueTuple miValueTuple( miValueResult ); if( !MIResponseFormFrameInfo( pc, fnName, miValueList.GetString(), fileName, path, nLine, miValueTuple ) ) return MIstatus::failure; vwrMiValueTuple = miValueTuple; 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 CMICmdCmdStackListArguments::Acknowledge( void ) { if( m_bThreadInvalid ) { // MI print "%s^done,stack-args=[]" const CMICmnMIValueList miValueList( true ); const CMICmnMIValueResult miValueResult( "stack-args", miValueList ); const CMICmnMIResultRecord miRecordResult( m_cmdData.nMiCmdNumber, CMICmnMIResultRecord::eResultClass_Done, miValueResult ); m_miResultRecord = miRecordResult; return MIstatus::success; } // MI print "%s^done,stack-args=[frame={level=\"0\",args=[%s]}]" const CMICmnMIValueConst miValueConst( "0" ); const CMICmnMIValueResult miValueResult( "level", miValueConst ); CMICmnMIValueTuple miValueTuple( miValueResult ); const CMICmnMIValueResult miValueResult2( "args", m_miValueList ); miValueTuple.Add( miValueResult2 ); const CMICmnMIValueResult miValueResult3( "frame", miValueTuple ); const CMICmnMIValueList miValueList( miValueResult3 ); const CMICmnMIValueResult miValueResult4( "stack-args", miValueList ); const CMICmnMIResultRecord miRecordResult( m_cmdData.nMiCmdNumber, CMICmnMIResultRecord::eResultClass_Done, miValueResult4 ); m_miResultRecord = miRecordResult; return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: Form MI partial response by appending more MI value type objects to the // tuple type object past in. // Type: Method. // Args: vrFrame - (R) LLDB thread object. // vMaskVarTypes - (R) 0x1000 = arguments, // 0x0100 = locals, // 0x0010 = statics, // 0x0001 = in scope only. // vwrMIValueList - (W) MI value list object. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo( const lldb::SBFrame & vrFrame, const MIuint vMaskVarTypes, CMICmnMIValueList & vwrMiValueList ) { bool bOk = MIstatus::success; lldb::SBFrame & rFrame = const_cast< lldb::SBFrame & >( vrFrame ); const bool bArg = (vMaskVarTypes & 0x1000); const bool bLocals = (vMaskVarTypes & 0x0100); const bool bStatics = (vMaskVarTypes & 0x0010); const bool bInScopeOnly = (vMaskVarTypes & 0x0001); const MIchar * pUnkwn = "??"; lldb::SBValueList listArg = rFrame.GetVariables( bArg, bLocals, bStatics, bInScopeOnly ); const MIuint nArgs = listArg.GetSize(); for( MIuint i = 0; bOk && (i < nArgs); i++ ) { lldb::SBValue val = listArg.GetValueAtIndex( i ); const char * pValue = val.GetValue(); pValue = (pValue != nullptr) ? pValue : pUnkwn; const char * pName = val.GetName(); pName = (pName != nullptr) ? pName : pUnkwn; const CMICmnMIValueConst miValueConst( pName ); const CMICmnMIValueResult miValueResult( "name", miValueConst ); CMICmnMIValueTuple miValueTuple( miValueResult ); const CMICmnMIValueConst miValueConst2( pValue ); const CMICmnMIValueResult miValueResult2( "value", miValueConst2 ); miValueTuple.Add( miValueResult2 ); bOk = vwrMiValueList.Add( miValueTuple ); } return bOk; }
//++ ------------------------------------------------------------------------------------ // 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 CMICmdCmdBreakEnable::Acknowledge( void ) { if( m_bBrkPtEnabledOk ) { const CMICmnMIValueConst miValueConst( CMIUtilString::Format( "%d", m_nBrkPtId ) ); const CMICmnMIValueResult miValueResult( "number", miValueConst ); CMICmnMIValueTuple miValueTuple( miValueResult ); const CMICmnMIValueConst miValueConst2( "y" ); const CMICmnMIValueResult miValueResult2( "enabled", miValueConst2 ); bool bOk = miValueTuple.Add( miValueResult2 ); const CMICmnMIValueResult miValueResult3( "bkpt", miValueTuple ); const CMICmnMIOutOfBandRecord miOutOfBandRecord( CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult3 ); bOk = bOk && CMICmnStreamStdout::TextToStdout( miOutOfBandRecord.GetString() ); const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Done ); m_miResultRecord = miRecordResult; return bOk; } const CMIUtilString strBrkPtId( CMIUtilString::Format( "%d", m_nBrkPtId ) ); const CMICmnMIValueConst miValueConst( CMIUtilString::Format( MIRSRC( IDS_CMD_ERR_BRKPT_INVALID ), strBrkPtId.c_str() ) ); const CMICmnMIValueResult miValueResult( "msg", miValueConst ); const CMICmnMIResultRecord miRecordResult( m_cmdData.strMiCmdToken, CMICmnMIResultRecord::eResultClass_Error, miValueResult ); m_miResultRecord = miRecordResult; return MIstatus::success; }
//++ ------------------------------------------------------------------------------------ // Details: Retrieve the specified thread's frame information. // Type: Method. // Args: vCmdData - (R) A command's information. // vThreadIdx - (R) Thread index. // vwrThreadFrames - (W) Frame data. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::GetThreadFrames( const SMICmdData & vCmdData, const MIuint vThreadIdx, CMICmnMIValueTuple & vwrThreadFrames ) { lldb::SBThread thread = m_lldbProcess.GetThreadByIndexID( vThreadIdx ); const uint32_t nFrames = thread.GetNumFrames(); if( nFrames == 0 ) { vwrThreadFrames = CMICmnMIValueTuple(); return MIstatus::success; } CMICmnMIValueTuple miValueTupleAll; for( MIuint nLevel = 0; nLevel < nFrames; nLevel++ ) { lldb::SBFrame frame = thread.GetFrameAtIndex( nLevel ); lldb::addr_t pc = 0; CMIUtilString fnName; CMIUtilString fileName; CMIUtilString path; MIuint nLine = 0; if( !GetFrameInfo( frame, pc, fnName, fileName, path, nLine ) ) return MIstatus::failure; // Function args CMICmnMIValueList miValueList( true ); const MIuint vMaskVarTypes = 0x1000; if( !MIResponseFormVariableInfo( frame, vMaskVarTypes, miValueList ) ) return MIstatus::failure; const MIchar * pUnknown = "??"; if( fnName != pUnknown ) { std::replace( fnName.begin(), fnName.end(), ')', ' ' ); std::replace( fnName.begin(), fnName.end(), '(', ' ' ); std::replace( fnName.begin(), fnName.end(), '\'', ' ' ); } const CMIUtilString strLevel( CMIUtilString::Format( "%d", nLevel ) ); const CMICmnMIValueConst miValueConst( strLevel ); const CMICmnMIValueResult miValueResult( "level", miValueConst ); miValueTupleAll.Add( miValueResult ); CMICmnMIValueTuple miValueTuple( miValueResult ); if( !MIResponseFormFrameInfo( pc, fnName, miValueList.GetString(), fileName, path, nLine, miValueTuple ) ) return MIstatus::failure; } vwrThreadFrames = miValueTupleAll; 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( 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 = (nThreadId != UINT64_MAX) ? rProcess.GetThreadByIndexID( nThreadId ) : rProcess.GetSelectedThread(); m_bThreadInvalid = !thread.IsValid(); if( m_bThreadInvalid ) return MIstatus::success; const lldb::StopReason eStopReason = thread.GetStopReason(); if( (eStopReason == lldb::eStopReasonNone) || (eStopReason == lldb::eStopReasonInvalid) ) { m_bThreadInvalid = true; return MIstatus::success; } const MIuint nFrames = thread.GetNumFrames(); for( MIuint i = 0; i < nFrames; i++ ) { lldb::SBFrame frame = thread.GetFrameAtIndex( i ); CMICmnMIValueList miValueList( true ); const MIuint maskVarTypes = 0x1000; if( !rSessionInfo.MIResponseFormVariableInfo3( frame, maskVarTypes, 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: Form MI partial response by appending more MI value type objects to the // tuple type object past in. // Type: Method. // Args: vId - (R) Break point ID. // vStrType - (R) Break point type. // vbDisp - (R) True = "del", false = "keep". // vbEnabled - (R) True = enabled, false = disabled break point. // 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. // vbHaveArgOptionThreadGrp - (R) True = include MI field, false = do not include "thread-groups". // vStrOptThrdGrp - (R) Thread group number. // vnTimes - (R) The count of the breakpoint existence. // vStrOrigLoc - (R) The name of the break point. // vwrMIValueTuple - (W) MI value tuple object. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::MIResponseFormBrkPtInfo( const lldb::break_id_t vId, const CMIUtilString & vStrType, const bool vbDisp, const bool vbEnabled, const lldb::addr_t vPc, const CMIUtilString & vFnName, const CMIUtilString & vFileName, const CMIUtilString & vPath, const MIuint vnLine, const bool vbHaveArgOptionThreadGrp, const CMIUtilString & vStrOptThrdGrp, const MIuint & vnTimes, const CMIUtilString & vStrOrigLoc, CMICmnMIValueTuple & vwrMiValueTuple ) { // MI print "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%08x\", func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}" // "number=" const CMIUtilString strN = CMIUtilString::Format( "%d", vId ); const CMICmnMIValueConst miValueConst( strN ); const CMICmnMIValueResult miValueResult( "number", miValueConst ); CMICmnMIValueTuple miValueTuple( miValueResult ); // "type=" const CMICmnMIValueConst miValueConst2( vStrType ); const CMICmnMIValueResult miValueResult2( "type", miValueConst2 ); bool bOk = miValueTuple.Add( miValueResult2 ); // "disp=" const CMICmnMIValueConst miValueConst3( vbDisp ? "del" : "keep" ); const CMICmnMIValueResult miValueResult3( "disp", miValueConst3 ); bOk = bOk && miValueTuple.Add( miValueResult3 ); // "enabled=" const CMICmnMIValueConst miValueConst4( vbEnabled ? "y" : "n" ); const CMICmnMIValueResult miValueResult4( "enabled", miValueConst4 ); bOk = bOk && miValueTuple.Add( miValueResult4 ); // "addr=" // "func=" // "file=" // "fullname=" // "line=" bOk = bOk && CMICmnLLDBDebugSessionInfo::Instance().MIResponseFormBrkPtFrameInfo( vPc, vFnName, vFileName, vPath, vnLine, miValueTuple ); if( vbHaveArgOptionThreadGrp ) { const CMICmnMIValueConst miValueConst( vStrOptThrdGrp ); const CMICmnMIValueList miValueList( miValueConst ); const CMICmnMIValueResult miValueResult( "thread-groups", miValueList ); bOk = bOk && miValueTuple.Add( miValueResult ); } // "times=" const CMIUtilString strN4 = CMIUtilString::Format( "%d", vnTimes ); const CMICmnMIValueConst miValueConstB( strN4 ); const CMICmnMIValueResult miValueResultB( "times", miValueConstB ); bOk = bOk && miValueTuple.Add( miValueResultB ); // "original-location=" const CMICmnMIValueConst miValueConstC( vStrOrigLoc ); const CMICmnMIValueResult miValueResultC( "original-location", miValueConstC ); bOk = bOk && miValueTuple.Add( miValueResultC ); vwrMiValueTuple = miValueTuple; 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: Form MI partial response by appending more MI value type objects to the // tuple type object past in. // Type: Method. // Args: vrBrkPtInfo - (R) Break point information object. // vwrMIValueTuple - (W) MI value tuple object. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::MIResponseFormBrkPtInfo(const SBrkPtInfo &vrBrkPtInfo, CMICmnMIValueTuple &vwrMiValueTuple) { // MI print "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016" PRIx64 "\", // func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}" // "number=" const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", vrBrkPtInfo.m_id)); const CMICmnMIValueResult miValueResult("number", miValueConst); CMICmnMIValueTuple miValueTuple(miValueResult); // "type=" const CMICmnMIValueConst miValueConst2(vrBrkPtInfo.m_strType); const CMICmnMIValueResult miValueResult2("type", miValueConst2); miValueTuple.Add(miValueResult2); // "disp=" const CMICmnMIValueConst miValueConst3(vrBrkPtInfo.m_bDisp ? "del" : "keep"); const CMICmnMIValueResult miValueResult3("disp", miValueConst3); miValueTuple.Add(miValueResult3); // "enabled=" const CMICmnMIValueConst miValueConst4(vrBrkPtInfo.m_bEnabled ? "y" : "n"); const CMICmnMIValueResult miValueResult4("enabled", miValueConst4); miValueTuple.Add(miValueResult4); // "addr=" // "func=" // "file=" // "fullname=" // "line=" MIResponseFormBrkPtFrameInfo(vrBrkPtInfo, miValueTuple); // "pending=" if (vrBrkPtInfo.m_bPending) { const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strOrigLoc); const CMICmnMIValueList miValueList(miValueConst); const CMICmnMIValueResult miValueResult("pending", miValueList); miValueTuple.Add(miValueResult); } if (vrBrkPtInfo.m_bHaveArgOptionThreadGrp) { const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strOptThrdGrp); const CMICmnMIValueList miValueList(miValueConst); const CMICmnMIValueResult miValueResult("thread-groups", miValueList); miValueTuple.Add(miValueResult); } // "times=" const CMICmnMIValueConst miValueConstB(CMIUtilString::Format("%d", vrBrkPtInfo.m_nTimes)); const CMICmnMIValueResult miValueResultB("times", miValueConstB); miValueTuple.Add(miValueResultB); // "thread=" if (vrBrkPtInfo.m_bBrkPtThreadId) { const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", vrBrkPtInfo.m_nBrkPtThreadId)); const CMICmnMIValueResult miValueResult("thread", miValueConst); miValueTuple.Add(miValueResult); } // "cond=" if (vrBrkPtInfo.m_bCondition) { const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strCondition); const CMICmnMIValueResult miValueResult("cond", miValueConst); miValueTuple.Add(miValueResult); } // "ignore=" if (vrBrkPtInfo.m_nIgnore != 0) { const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", vrBrkPtInfo.m_nIgnore)); const CMICmnMIValueResult miValueResult("ignore", miValueConst); miValueTuple.Add(miValueResult); } // "original-location=" const CMICmnMIValueConst miValueConstC(vrBrkPtInfo.m_strOrigLoc); const CMICmnMIValueResult miValueResultC("original-location", miValueConstC); miValueTuple.Add(miValueResultC); vwrMiValueTuple = miValueTuple; return MIstatus::success; }