//===-- MICmnLLDBDebugSessionInfo.cpp ---------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// //++ // File: MICmnLLDBDebugSessionInfo.cpp // // Overview: CMICmnLLDBDebugSessionInfo implementation. // // Environment: Compilers: Visual C++ 12. // gcc (Ubuntu/Linaro 4.8.1-10ubuntu9) 4.8.1 // Libraries: See MIReadmetxt. // // Copyright: None. //-- // Third party headers: #include #ifdef _WIN32 #include // For the ::_access() #else #include // For the ::access() #endif // _WIN32 #include // In-house headers: #include "MICmnLLDBDebugSessionInfo.h" #include "MICmnLLDBDebugger.h" #include "MICmnResources.h" #include "MICmnMIResultRecord.h" #include "MICmnMIValueConst.h" #include "MICmnMIValueList.h" #include "MICmnMIValueTuple.h" #include "MICmdData.h" #include "MICmnLLDBUtilSBValue.h" //++ ------------------------------------------------------------------------------------ // Details: CMICmnLLDBDebugSessionInfo constructor. // Type: Method. // Args: None. // Return: None. // Throws: None. //-- CMICmnLLDBDebugSessionInfo::CMICmnLLDBDebugSessionInfo(void) : m_rLldbDebugger(CMICmnLLDBDebugger::Instance().GetTheDebugger()) , m_rLlldbListener(CMICmnLLDBDebugger::Instance().GetTheListener()) , m_nBrkPointCntMax(INT32_MAX) , m_currentSelectedThread(LLDB_INVALID_THREAD_ID) , m_constStrSharedDataKeyWkDir("Working Directory") , m_constStrSharedDataSolibPath("Solib Path") { } //++ ------------------------------------------------------------------------------------ // Details: CMICmnLLDBDebugSessionInfo destructor. // Type: Overridable. // Args: None. // Return: None. // Throws: None. //-- CMICmnLLDBDebugSessionInfo::~CMICmnLLDBDebugSessionInfo(void) { Shutdown(); } //++ ------------------------------------------------------------------------------------ // Details: Initialize resources for *this object. // Type: Method. // Args: None. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::Initialize(void) { m_clientUsageRefCnt++; if (m_bInitialized) return MIstatus::success; m_currentSelectedThread = LLDB_INVALID_THREAD_ID; CMICmnLLDBDebugSessionInfoVarObj::VarObjIdResetToZero(); m_bInitialized = MIstatus::success; return m_bInitialized; } //++ ------------------------------------------------------------------------------------ // Details: Release resources for *this object. // Type: Method. // Args: None. // Return: MIstatus::success - Functionality succeeded. // MIstatus::failure - Functionality failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::Shutdown(void) { if (--m_clientUsageRefCnt > 0) return MIstatus::success; if (!m_bInitialized) return MIstatus::success; bool bOk = MIstatus::success; CMIUtilString errMsg; // Tidy up bOk = SharedDataDestroy(); if (!bOk) { errMsg = CMIUtilString::Format(MIRSRC(IDS_DBGSESSION_ERR_SHARED_DATA_RELEASE)); errMsg += "\n"; } m_vecActiveThreadId.clear(); CMICmnLLDBDebugSessionInfoVarObj::VarObjClear(); m_bInitialized = false; return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Command instances can create and share data between other instances of commands. // Data can also be assigned by a command and retrieved by LLDB event handler. // This function takes down those resources build up over the use of the commands. // This function should be called when the creation and running of command has // stopped i.e. application shutdown. // Type: Method. // Args: None. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::SharedDataDestroy(void) { m_mapIdToSessionData.Clear(); m_vecVarObj.clear(); m_mapBrkPtIdToBrkPtInfo.clear(); return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Record information about a LLDB break point so that is can be recalled in other // commands or LLDB event handling functions. // Type: Method. // Args: vBrkPtId - (R) LLDB break point ID. // vrBrkPtInfo - (R) Break point information object. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::RecordBrkPtInfo(const MIuint vnBrkPtId, const SBrkPtInfo &vrBrkPtInfo) { MapPairBrkPtIdToBrkPtInfo_t pr(vnBrkPtId, vrBrkPtInfo); m_mapBrkPtIdToBrkPtInfo.insert(pr); return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Retrieve information about a LLDB break point previous recorded either by // commands or LLDB event handling functions. // Type: Method. // Args: vBrkPtId - (R) LLDB break point ID. // vrwBrkPtInfo - (W) Break point information object. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::RecordBrkPtInfoGet(const MIuint vnBrkPtId, SBrkPtInfo &vrwBrkPtInfo) const { const MapBrkPtIdToBrkPtInfo_t::const_iterator it = m_mapBrkPtIdToBrkPtInfo.find(vnBrkPtId); if (it != m_mapBrkPtIdToBrkPtInfo.end()) { vrwBrkPtInfo = (*it).second; return MIstatus::success; } return MIstatus::failure; } //++ ------------------------------------------------------------------------------------ // Details: Delete information about a specific LLDB break point object. This function // should be called when a LLDB break point is deleted. // Type: Method. // Args: vBrkPtId - (R) LLDB break point ID. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::RecordBrkPtInfoDelete(const MIuint vnBrkPtId) { const MapBrkPtIdToBrkPtInfo_t::const_iterator it = m_mapBrkPtIdToBrkPtInfo.find(vnBrkPtId); if (it != m_mapBrkPtIdToBrkPtInfo.end()) { m_mapBrkPtIdToBrkPtInfo.erase(it); return MIstatus::success; } return MIstatus::failure; } //++ ------------------------------------------------------------------------------------ // 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, CMIUtilString &vwrThreadFrames) { lldb::SBThread thread = m_lldbProcess.GetThreadByIndexID(vThreadIdx); const uint32_t nFrames = thread.GetNumFrames(); if (nFrames == 0) { // MI print "frame={}" CMICmnMIValueTuple miValueTuple; CMICmnMIValueResult miValueResult("frame", miValueTuple); vwrThreadFrames = miValueResult.GetString(); return MIstatus::success; } // MI print // "frame={level=\"%d\",addr=\"0x%08llx\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"},frame={level=\"%d\",addr=\"0x%08llx\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"}, // ..." CMIUtilString strListCommaSeperated; 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 maskVarTypes = eVariableType_Arguments; if (!MIResponseFormVariableInfo(frame, maskVarTypes, 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(), '\'', ' '); } CMICmnMIValueTuple miValueTuple; const CMIUtilString strLevel(CMIUtilString::Format("%d", nLevel)); const CMICmnMIValueConst miValueConst(strLevel); const CMICmnMIValueResult miValueResult("level", miValueConst); miValueTuple.Add(miValueResult); if (!MIResponseFormFrameInfo2(pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple)) return MIstatus::failure; const CMICmnMIValueResult miValueResult2("frame", miValueTuple); if (nLevel != 0) strListCommaSeperated += ","; strListCommaSeperated += miValueResult2.GetString(); } vwrThreadFrames = strListCommaSeperated; return MIstatus::success; } // Todo: Refactor maybe to so only one function with this name, but not just yet //++ ------------------------------------------------------------------------------------ // 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::GetThreadFrames2(const SMICmdData &vCmdData, const MIuint vThreadIdx, CMIUtilString &vwrThreadFrames) { lldb::SBThread thread = m_lldbProcess.GetThreadByIndexID(vThreadIdx); const uint32_t nFrames = thread.GetNumFrames(); if (nFrames == 0) { // MI print "frame={}" CMICmnMIValueTuple miValueTuple; CMICmnMIValueResult miValueResult("frame", miValueTuple); vwrThreadFrames = miValueResult.GetString(); return MIstatus::success; } // MI print // "frame={level=\"%d\",addr=\"0x%08llx\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"},frame={level=\"%d\",addr=\"0x%08llx\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"}, // ..." CMIUtilString strListCommaSeperated; 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 maskVarTypes = eVariableType_Arguments; if (!MIResponseFormVariableInfo2(frame, maskVarTypes, 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(), '\'', ' '); } CMICmnMIValueTuple miValueTuple; const CMIUtilString strLevel(CMIUtilString::Format("%d", nLevel)); const CMICmnMIValueConst miValueConst(strLevel); const CMICmnMIValueResult miValueResult("level", miValueConst); miValueTuple.Add(miValueResult); if (!MIResponseFormFrameInfo2(pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple)) return MIstatus::failure; const CMICmnMIValueResult miValueResult2("frame", miValueTuple); if (nLevel != 0) strListCommaSeperated += ","; strListCommaSeperated += miValueResult2.GetString(); } vwrThreadFrames = strListCommaSeperated; return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Return the resolved file's path for the given file. // Type: Method. // Args: vCmdData - (R) A command's information. // vPath - (R) Original path. // vwrResolvedPath - (W) Resolved path. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::ResolvePath(const SMICmdData &vCmdData, const CMIUtilString &vPath, CMIUtilString &vwrResolvedPath) { // ToDo: Verify this code as it does not work as vPath is always empty CMIUtilString strResolvedPath; if (!SharedDataRetrieve(m_constStrSharedDataKeyWkDir, strResolvedPath)) { vwrResolvedPath = ""; SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_SHARED_DATA_NOT_FOUND), vCmdData.strMiCmd.c_str(), m_constStrSharedDataKeyWkDir.c_str())); return MIstatus::failure; } vwrResolvedPath = vPath; return ResolvePath(strResolvedPath, vwrResolvedPath); } //++ ------------------------------------------------------------------------------------ // 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: Determine the given file path exists or not. // Type: Method. // Args: vPath - (R) File name path. // vwbYesAccessible - (W) True - file exists, false = does not exist. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::AccessPath(const CMIUtilString &vPath, bool &vwbYesAccessible) { #ifdef _WIN32 vwbYesAccessible = (::_access(vPath.c_str(), 0) == 0); #else vwbYesAccessible = (::access(vPath.c_str(), 0) == 0); #endif // _WIN32 return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Form MI partial response by appending more MI value type objects to the // tuple type object past in. // Type: Method. // Args: vCmdData - (R) A command's information. // vrThread - (R) LLDB thread object. // vwrMIValueTuple - (W) MI value tuple object. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo(const SMICmdData &vCmdData, const lldb::SBThread &vrThread, CMICmnMIValueTuple &vwrMIValueTuple) { lldb::SBThread &rThread = const_cast(vrThread); CMIUtilString strFrames; if (!GetThreadFrames(vCmdData, rThread.GetIndexID(), strFrames)) return MIstatus::failure; const bool bSuspended = rThread.IsSuspended(); const lldb::StopReason eReason = rThread.GetStopReason(); const bool bValidReason = !((eReason == lldb::eStopReasonNone) || (eReason == lldb::eStopReasonInvalid)); const CMIUtilString strState((bSuspended || bValidReason) ? "stopped" : "running"); // Add "id" const CMIUtilString strId(CMIUtilString::Format("%d", rThread.GetIndexID())); const CMICmnMIValueConst miValueConst1(strId); const CMICmnMIValueResult miValueResult1("id", miValueConst1); if (!vwrMIValueTuple.Add(miValueResult1)) return MIstatus::failure; // Add "target-id" const MIchar *pThreadName = rThread.GetName(); const MIuint len = (pThreadName != nullptr) ? CMIUtilString(pThreadName).length() : 0; const bool bHaveName = ((pThreadName != nullptr) && (len > 0) && (len < 32) && CMIUtilString::IsAllValidAlphaAndNumeric(*pThreadName)); // 32 is arbitary number const MIchar *pThrdFmt = bHaveName ? "%s" : "Thread %d"; CMIUtilString strThread; if (bHaveName) strThread = CMIUtilString::Format(pThrdFmt, pThreadName); else strThread = CMIUtilString::Format(pThrdFmt, rThread.GetIndexID()); const CMICmnMIValueConst miValueConst2(strThread); const CMICmnMIValueResult miValueResult2("target-id", miValueConst2); if (!vwrMIValueTuple.Add(miValueResult2)) return MIstatus::failure; // Add "frame" const CMICmnMIValueConst miValueConst3(strFrames, true); if (!vwrMIValueTuple.Add(miValueConst3, false)) return MIstatus::failure; // Add "state" const CMICmnMIValueConst miValueConst4(strState); const CMICmnMIValueResult miValueResult4("state", miValueConst4); if (!vwrMIValueTuple.Add(miValueResult4)) return MIstatus::failure; return MIstatus::success; } // Todo: Refactor maybe to so only one function with this name, but not just yet //++ ------------------------------------------------------------------------------------ // Details: Form MI partial response by appending more MI value type objects to the // tuple type object past in. // Type: Method. // Args: vCmdData - (R) A command's information. // vrThread - (R) LLDB thread object. // vwrMIValueTuple - (W) MI value tuple object. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo3(const SMICmdData &vCmdData, const lldb::SBThread &vrThread, CMICmnMIValueTuple &vwrMIValueTuple) { lldb::SBThread &rThread = const_cast(vrThread); CMIUtilString strFrames; if (!GetThreadFrames2(vCmdData, rThread.GetIndexID(), strFrames)) return MIstatus::failure; const bool bSuspended = rThread.IsSuspended(); const lldb::StopReason eReason = rThread.GetStopReason(); const bool bValidReason = !((eReason == lldb::eStopReasonNone) || (eReason == lldb::eStopReasonInvalid)); const CMIUtilString strState((bSuspended || bValidReason) ? "stopped" : "running"); // Add "id" const CMIUtilString strId(CMIUtilString::Format("%d", rThread.GetIndexID())); const CMICmnMIValueConst miValueConst1(strId); const CMICmnMIValueResult miValueResult1("id", miValueConst1); if (!vwrMIValueTuple.Add(miValueResult1)) return MIstatus::failure; // Add "target-id" const MIchar *pThreadName = rThread.GetName(); const MIuint len = (pThreadName != nullptr) ? CMIUtilString(pThreadName).length() : 0; const bool bHaveName = ((pThreadName != nullptr) && (len > 0) && (len < 32) && CMIUtilString::IsAllValidAlphaAndNumeric(*pThreadName)); // 32 is arbitary number const MIchar *pThrdFmt = bHaveName ? "%s" : "Thread %d"; CMIUtilString strThread; if (bHaveName) strThread = CMIUtilString::Format(pThrdFmt, pThreadName); else strThread = CMIUtilString::Format(pThrdFmt, rThread.GetIndexID()); const CMICmnMIValueConst miValueConst2(strThread); const CMICmnMIValueResult miValueResult2("target-id", miValueConst2); if (!vwrMIValueTuple.Add(miValueResult2)) return MIstatus::failure; // Add "frame" const CMICmnMIValueConst miValueConst3(strFrames, true); if (!vwrMIValueTuple.Add(miValueConst3, false)) return MIstatus::failure; // Add "state" const CMICmnMIValueConst miValueConst4(strState); const CMICmnMIValueResult miValueResult4("state", miValueConst4); if (!vwrMIValueTuple.Add(miValueResult4)) return MIstatus::failure; return MIstatus::success; } // Todo: Refactor maybe to so only one function with this name, but not just yet //++ ------------------------------------------------------------------------------------ // Details: Form MI partial response by appending more MI value type objects to the // tuple type object past in. // Type: Method. // Args: vCmdData - (R) A command's information. // vrThread - (R) LLDB thread object. // vwrMIValueTuple - (W) MI value tuple object. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::MIResponseFormThreadInfo2(const SMICmdData &vCmdData, const lldb::SBThread &vrThread, CMICmnMIValueTuple &vwrMIValueTuple) { lldb::SBThread &rThread = const_cast(vrThread); const bool bSuspended = rThread.IsSuspended(); const lldb::StopReason eReason = rThread.GetStopReason(); const bool bValidReason = !((eReason == lldb::eStopReasonNone) || (eReason == lldb::eStopReasonInvalid)); const CMIUtilString strState((bSuspended || bValidReason) ? "stopped" : "running"); // Add "id" const CMIUtilString strId(CMIUtilString::Format("%d", rThread.GetIndexID())); const CMICmnMIValueConst miValueConst1(strId); const CMICmnMIValueResult miValueResult1("id", miValueConst1); if (!vwrMIValueTuple.Add(miValueResult1)) return MIstatus::failure; // Add "target-id" const MIchar *pThreadName = rThread.GetName(); const MIuint len = (pThreadName != nullptr) ? CMIUtilString(pThreadName).length() : 0; const bool bHaveName = ((pThreadName != nullptr) && (len > 0) && (len < 32) && CMIUtilString::IsAllValidAlphaAndNumeric(*pThreadName)); // 32 is arbitary number const MIchar *pThrdFmt = bHaveName ? "%s" : "Thread %d"; CMIUtilString strThread; if (bHaveName) strThread = CMIUtilString::Format(pThrdFmt, pThreadName); else strThread = CMIUtilString::Format(pThrdFmt, rThread.GetIndexID()); const CMICmnMIValueConst miValueConst2(strThread); const CMICmnMIValueResult miValueResult2("target-id", miValueConst2); if (!vwrMIValueTuple.Add(miValueResult2)) return MIstatus::failure; // Add "state" const CMICmnMIValueConst miValueConst4(strState); const CMICmnMIValueResult miValueResult4("state", miValueConst4); if (!vwrMIValueTuple.Add(miValueResult4)) return MIstatus::failure; return MIstatus::success; } // Todo: Refactor maybe to so only one function with this name, but not just yet //++ ------------------------------------------------------------------------------------ // 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) Construed according to VariableType_e. // vwrMIValueList - (W) MI value list object. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo2(const lldb::SBFrame &vrFrame, const MIuint vMaskVarTypes, CMICmnMIValueList &vwrMiValueList) { bool bOk = MIstatus::success; lldb::SBFrame &rFrame = const_cast(vrFrame); const bool bArg = (vMaskVarTypes & eVariableType_Arguments); const bool bLocals = (vMaskVarTypes & eVariableType_Locals); const bool bStatics = (vMaskVarTypes & eVariableType_Statics); const bool bInScopeOnly = (vMaskVarTypes & eVariableType_InScope); lldb::SBValueList listArg = rFrame.GetVariables(bArg, bLocals, bStatics, bInScopeOnly); const MIuint nArgs = listArg.GetSize(); for (MIuint i = 0; bOk && (i < nArgs); i++) { lldb::SBValue value = listArg.GetValueAtIndex(i); const CMICmnLLDBUtilSBValue utilValue(value); const CMICmnMIValueConst miValueConst(utilValue.GetName()); const CMICmnMIValueResult miValueResult("name", miValueConst); CMICmnMIValueTuple miValueTuple(miValueResult); const CMICmnMIValueConst miValueConst2(utilValue.GetValue()); const CMICmnMIValueResult miValueResult2("value", miValueConst2); miValueTuple.Add(miValueResult2); bOk = vwrMiValueList.Add(miValueTuple); } return bOk; } //++ ------------------------------------------------------------------------------------ // 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) Construed according to VariableType_e. // 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(vrFrame); const bool bArg = (vMaskVarTypes & eVariableType_Arguments); const bool bLocals = (vMaskVarTypes & eVariableType_Locals); const bool bStatics = (vMaskVarTypes & eVariableType_Statics); const bool bInScopeOnly = (vMaskVarTypes & eVariableType_InScope); const MIuint nMaxRecusiveDepth = 10; MIuint nCurrentRecursiveDepth = 0; lldb::SBValueList listArg = rFrame.GetVariables(bArg, bLocals, bStatics, bInScopeOnly); const MIuint nArgs = listArg.GetSize(); for (MIuint i = 0; bOk && (i < nArgs); i++) { lldb::SBValue value = listArg.GetValueAtIndex(i); bOk = GetVariableInfo(nMaxRecusiveDepth, value, false, vwrMiValueList, nCurrentRecursiveDepth); } return bOk; } // *** Do not refactor this function to be one function with same name as it can break more than // *** than one stack type command //++ ------------------------------------------------------------------------------------ // 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) Construed according to VariableType_e. // vwrMIValueList - (W) MI value list object. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::MIResponseFormVariableInfo3(const lldb::SBFrame &vrFrame, const MIuint vMaskVarTypes, CMICmnMIValueList &vwrMiValueList) { bool bOk = MIstatus::success; lldb::SBFrame &rFrame = const_cast(vrFrame); const bool bArg = (vMaskVarTypes & eVariableType_Arguments); const bool bLocals = (vMaskVarTypes & eVariableType_Locals); const bool bStatics = (vMaskVarTypes & eVariableType_Statics); const bool bInScopeOnly = (vMaskVarTypes & eVariableType_InScope); const MIuint nMaxRecusiveDepth = 10; MIuint nCurrentRecursiveDepth = 0; lldb::SBValueList listArg = rFrame.GetVariables(bArg, bLocals, bStatics, bInScopeOnly); const MIuint nArgs = listArg.GetSize(); for (MIuint i = 0; bOk && (i < nArgs); i++) { lldb::SBValue value = listArg.GetValueAtIndex(i); bOk = GetVariableInfo2(nMaxRecusiveDepth, value, false, vwrMiValueList, nCurrentRecursiveDepth); } return bOk; } // *** Do not refactor this function to be one function with same name as it can break more than // *** than one stack type command //++ ------------------------------------------------------------------------------------ // Details: Extract the value's name and value or recurse into child value object. // Type: Method. // Args: vnMaxDepth - (R) The max recursive depth for this function. // vrValue - (R) LLDB value object. // vbIsChildValue - (R) True = Value object is a child of a higher Value object, // - False = Value object not a child. // vwrMIValueList - (W) MI value list object. // vnDepth - (RW) The current recursive depth of this function. // // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::GetVariableInfo(const MIuint vnMaxDepth, const lldb::SBValue &vrValue, const bool vbIsChildValue, CMICmnMIValueList &vwrMiValueList, MIuint &vrwnDepth) { // *** Update GetVariableInfo2() with any code changes here *** // Check recursive depth if (vrwnDepth >= vnMaxDepth) return MIstatus::success; bool bOk = MIstatus::success; lldb::SBValue &rValue = const_cast(vrValue); const CMICmnLLDBUtilSBValue utilValue(vrValue, true); CMICmnMIValueTuple miValueTuple; const MIchar *pName = rValue.GetName(); MIunused(pName); const bool bIsPointerType = rValue.GetType().IsPointerType(); const MIuint nChildren = rValue.GetNumChildren(); if (nChildren == 0) { if (vbIsChildValue) { if (utilValue.IsCharType()) { // For char types and try to form text string const CMICmnMIValueConst miValueConst(utilValue.GetValue().c_str(), true); miValueTuple.Add(miValueConst, true); } else { // For composite types const CMICmnMIValueConst miValueConst( CMIUtilString::Format("%s = %s", utilValue.GetName().c_str(), utilValue.GetValue().c_str()), true); miValueTuple.Add(miValueConst, true); } return vwrMiValueList.Add(CMICmnMIValueConst(miValueTuple.ExtractContentNoBrackets(), true)); } else { // Basic types const CMICmnMIValueConst miValueConst(utilValue.GetName()); const CMICmnMIValueResult miValueResult("name", miValueConst); miValueTuple.Add(miValueResult); const CMICmnMIValueConst miValueConst2(utilValue.GetValue()); const CMICmnMIValueResult miValueResult2("value", miValueConst2); miValueTuple.Add(miValueResult2); return vwrMiValueList.Add(miValueTuple); } } else if (bIsPointerType && utilValue.IsChildCharType()) { // Append string text to the parent value information const CMICmnMIValueConst miValueConst(utilValue.GetName()); const CMICmnMIValueResult miValueResult("name", miValueConst); miValueTuple.Add(miValueResult); const CMIUtilString &rText(utilValue.GetChildValueCString()); if (rText.empty()) { const CMICmnMIValueConst miValueConst(utilValue.GetValue()); const CMICmnMIValueResult miValueResult("value", miValueConst); miValueTuple.Add(miValueResult); } else { if (utilValue.IsValueUnknown()) { const CMICmnMIValueConst miValueConst(rText); const CMICmnMIValueResult miValueResult("value", miValueConst); miValueTuple.Add(miValueResult); } else { // Note code that has const in will not show the text suffix to the string pointer // i.e. const char * pMyStr = "blah"; ==> "0x00007000"" <-- Eclipse shows this // but char * pMyStr = "blah"; ==> "0x00007000" "blah"" <-- Eclipse shows this const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%s %s", utilValue.GetValue().c_str(), rText.c_str())); const CMICmnMIValueResult miValueResult("value", miValueConst); miValueTuple.Add(miValueResult); } } return vwrMiValueList.Add(miValueTuple); } else if (bIsPointerType) { if (vbIsChildValue) { // For composite types const CMICmnMIValueConst miValueConst( CMIUtilString::Format("%s = %s", utilValue.GetName().c_str(), utilValue.GetValue().c_str()), true); miValueTuple.Add(miValueConst, true); return vwrMiValueList.Add(CMICmnMIValueConst(miValueTuple.ExtractContentNoBrackets(), true)); } else { // Basic types const CMICmnMIValueConst miValueConst(utilValue.GetName()); const CMICmnMIValueResult miValueResult("name", miValueConst); miValueTuple.Add(miValueResult); const CMICmnMIValueConst miValueConst2(utilValue.GetValue()); const CMICmnMIValueResult miValueResult2("value", miValueConst2); miValueTuple.Add(miValueResult2); return vwrMiValueList.Add(miValueTuple); } } else { // Build parent child composite types CMICmnMIValueList miValueList(true); for (MIuint i = 0; bOk && (i < nChildren); i++) { lldb::SBValue member = rValue.GetChildAtIndex(i); bOk = GetVariableInfo(vnMaxDepth, member, true, miValueList, ++vrwnDepth); } const CMICmnMIValueConst miValueConst(utilValue.GetName()); const CMICmnMIValueResult miValueResult("name", miValueConst); miValueTuple.Add(miValueResult); const CMICmnMIValueConst miValueConst2(CMIUtilString::Format("{%s}", miValueList.ExtractContentNoBrackets().c_str())); const CMICmnMIValueResult miValueResult2("value", miValueConst2); miValueTuple.Add(miValueResult2); return vwrMiValueList.Add(miValueTuple); } } // *** Do not refactor this function to be one function with same name as it can break more than // *** than one stack type command //++ ------------------------------------------------------------------------------------ // Details: Extract the value's name and value or recurse into child value object. // Type: Method. // Args: vnMaxDepth - (R) The max recursive depth for this function. // vrValue - (R) LLDB value object. // vbIsChildValue - (R) True = Value object is a child of a higher Value object, // - False = Value object not a child. // vwrMIValueList - (W) MI value list object. // vnDepth - (RW) The current recursive depth of this function. // // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::GetVariableInfo2(const MIuint vnMaxDepth, const lldb::SBValue &vrValue, const bool vbIsChildValue, CMICmnMIValueList &vwrMiValueList, MIuint &vrwnDepth) { // *** Update GetVariableInfo() with any code changes here *** // Check recursive depth if (vrwnDepth >= vnMaxDepth) return MIstatus::success; bool bOk = MIstatus::success; lldb::SBValue &rValue = const_cast(vrValue); const CMICmnLLDBUtilSBValue utilValue(vrValue, true); CMICmnMIValueTuple miValueTuple; const MIchar *pName = rValue.GetName(); MIunused(pName); const MIuint nChildren = rValue.GetNumChildren(); if (nChildren == 0) { if (vbIsChildValue && utilValue.IsCharType()) { // For char types and try to form text string const CMICmnMIValueConst miValueConst(utilValue.GetValue().c_str(), true); miValueTuple.Add(miValueConst, true); return vwrMiValueList.Add(CMICmnMIValueConst(miValueTuple.ExtractContentNoBrackets(), true)); } else { // Basic types const CMICmnMIValueConst miValueConst(utilValue.GetName()); const CMICmnMIValueResult miValueResult("name", miValueConst); miValueTuple.Add(miValueResult); const CMICmnMIValueConst miValueConst2(utilValue.GetValue()); const CMICmnMIValueResult miValueResult2("value", miValueConst2); miValueTuple.Add(miValueResult2); return vwrMiValueList.Add(miValueTuple); } } else if (utilValue.IsChildCharType()) { // Append string text to the parent value information const CMICmnMIValueConst miValueConst(utilValue.GetName()); const CMICmnMIValueResult miValueResult("name", miValueConst); miValueTuple.Add(miValueResult); const CMIUtilString &rText(utilValue.GetChildValueCString()); if (rText.empty()) { const CMICmnMIValueConst miValueConst(utilValue.GetValue()); const CMICmnMIValueResult miValueResult("value", miValueConst); miValueTuple.Add(miValueResult); } else { if (utilValue.IsValueUnknown()) { const CMICmnMIValueConst miValueConst(rText); const CMICmnMIValueResult miValueResult("value", miValueConst); miValueTuple.Add(miValueResult); } else { // Note code that has const in will not show the text suffix to the string pointer // i.e. const char * pMyStr = "blah"; ==> "0x00007000"" <-- Eclipse shows this // but char * pMyStr = "blah"; ==> "0x00007000" "blah"" <-- Eclipse shows this const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%s %s", utilValue.GetValue().c_str(), rText.c_str())); const CMICmnMIValueResult miValueResult("value", miValueConst); miValueTuple.Add(miValueResult); } } return vwrMiValueList.Add(miValueTuple); } else { // Build parent child composite types CMICmnMIValueList miValueList(true); for (MIuint i = 0; bOk && (i < nChildren); i++) { lldb::SBValue member = rValue.GetChildAtIndex(i); bOk = GetVariableInfo(vnMaxDepth, member, true, miValueList, ++vrwnDepth); } const CMICmnMIValueConst miValueConst(utilValue.GetName()); const CMICmnMIValueResult miValueResult("name", miValueConst); miValueTuple.Add(miValueResult); const CMICmnMIValueConst miValueConst2(CMIUtilString::Format("{%s}", miValueList.ExtractContentNoBrackets().c_str())); const CMICmnMIValueResult miValueResult2("value", miValueConst2); miValueTuple.Add(miValueResult2); return vwrMiValueList.Add(miValueTuple); } } //++ ------------------------------------------------------------------------------------ // 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(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; // MI print "{level=\"0\",addr=\"0x%08llx\",func=\"%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, fileName, path, nLine, miValueTuple)) return MIstatus::failure; vwrMiValueTuple = miValueTuple; return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Retrieve the frame information from LLDB frame object. // Type: Method. // Args: vrFrame - (R) LLDB thread object. // vPc - (W) Address number. // vFnName - (W) Function name. // vFileName - (W) File name text. // vPath - (W) Full file name and path text. // vnLine - (W) File line number. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::GetFrameInfo(const lldb::SBFrame &vrFrame, lldb::addr_t &vwPc, CMIUtilString &vwFnName, CMIUtilString &vwFileName, CMIUtilString &vwPath, MIuint &vwnLine) { lldb::SBFrame &rFrame = const_cast(vrFrame); static char pBuffer[MAX_PATH]; const MIuint nBytes = rFrame.GetLineEntry().GetFileSpec().GetPath(&pBuffer[0], sizeof(pBuffer)); MIunused(nBytes); CMIUtilString strResolvedPath(&pBuffer[0]); const MIchar *pUnkwn = "??"; if (!ResolvePath(pUnkwn, strResolvedPath)) return MIstatus::failure; vwPath = strResolvedPath; vwPc = rFrame.GetPC(); const MIchar *pFnName = rFrame.GetFunctionName(); vwFnName = (pFnName != nullptr) ? pFnName : pUnkwn; const MIchar *pFileName = rFrame.GetLineEntry().GetFileSpec().GetFilename(); vwFileName = (pFileName != nullptr) ? pFileName : pUnkwn; vwnLine = rFrame.GetLineEntry().GetLine(); 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: vPc - (R) Address number. // vFnName - (R) Function name. // vFileName - (R) File name text. // vPath - (R) Full file name and path text. // vnLine - (R) File line number. // vwrMIValueTuple - (W) MI value tuple object. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo(const lldb::addr_t vPc, const CMIUtilString &vFnName, const CMIUtilString &vFileName, const CMIUtilString &vPath, const MIuint vnLine, CMICmnMIValueTuple &vwrMiValueTuple) { const CMIUtilString strAddr(CMIUtilString::Format("0x%08llx", vPc)); const CMICmnMIValueConst miValueConst2(strAddr); const CMICmnMIValueResult miValueResult2("addr", miValueConst2); if (!vwrMiValueTuple.Add(miValueResult2)) return MIstatus::failure; const CMICmnMIValueConst miValueConst3(vFnName); const CMICmnMIValueResult miValueResult3("func", miValueConst3); if (!vwrMiValueTuple.Add(miValueResult3)) return MIstatus::failure; const CMICmnMIValueConst miValueConst5(vFileName); const CMICmnMIValueResult miValueResult5("file", miValueConst5); if (!vwrMiValueTuple.Add(miValueResult5)) return MIstatus::failure; const CMICmnMIValueConst miValueConst6(vPath); const CMICmnMIValueResult miValueResult6("fullname", miValueConst6); if (!vwrMiValueTuple.Add(miValueResult6)) return MIstatus::failure; const CMIUtilString strLine(CMIUtilString::Format("%d", vnLine)); const CMICmnMIValueConst miValueConst7(strLine); const CMICmnMIValueResult miValueResult7("line", miValueConst7); if (!vwrMiValueTuple.Add(miValueResult7)) return MIstatus::failure; return MIstatus::success; } // Todo: Refactor maybe to so only one function with this name, but not just yet //++ ------------------------------------------------------------------------------------ // Details: Form MI partial response by appending more MI value type objects to the // tuple type object past in. // Type: Method. // Args: vPc - (R) Address number. // vArgInfo - (R) Args information in MI response form. // vFnName - (R) Function name. // vFileName - (R) File name text. // vPath - (R) Full file name and path text. // vnLine - (R) File line number. // vwrMIValueTuple - (W) MI value tuple object. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo2(const lldb::addr_t vPc, const CMIUtilString &vArgInfo, const CMIUtilString &vFnName, const CMIUtilString &vFileName, const CMIUtilString &vPath, const MIuint vnLine, CMICmnMIValueTuple &vwrMiValueTuple) { const CMIUtilString strAddr(CMIUtilString::Format("0x%08llx", vPc)); const CMICmnMIValueConst miValueConst2(strAddr); const CMICmnMIValueResult miValueResult2("addr", miValueConst2); if (!vwrMiValueTuple.Add(miValueResult2)) return MIstatus::failure; const CMICmnMIValueConst miValueConst3(vFnName); const CMICmnMIValueResult miValueResult3("func", miValueConst3); if (!vwrMiValueTuple.Add(miValueResult3)) return MIstatus::failure; const CMICmnMIValueConst miValueConst4(vArgInfo, true); const CMICmnMIValueResult miValueResult4("args", miValueConst4); if (!vwrMiValueTuple.Add(miValueResult4)) return MIstatus::failure; const CMICmnMIValueConst miValueConst5(vFileName); const CMICmnMIValueResult miValueResult5("file", miValueConst5); if (!vwrMiValueTuple.Add(miValueResult5)) return MIstatus::failure; const CMICmnMIValueConst miValueConst6(vPath); const CMICmnMIValueResult miValueResult6("fullname", miValueConst6); if (!vwrMiValueTuple.Add(miValueResult6)) return MIstatus::failure; const CMIUtilString strLine(CMIUtilString::Format("%d", vnLine)); const CMICmnMIValueConst miValueConst7(strLine); const CMICmnMIValueResult miValueResult7("line", miValueConst7); if (!vwrMiValueTuple.Add(miValueResult7)) return MIstatus::failure; return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: 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::MIResponseFormBrkPtFrameInfo(const SBrkPtInfo &vrBrkPtInfo, CMICmnMIValueTuple &vwrMiValueTuple) { const CMIUtilString strAddr(CMIUtilString::Format("0x%08llx", vrBrkPtInfo.m_pc)); const CMICmnMIValueConst miValueConst2(strAddr); const CMICmnMIValueResult miValueResult2("addr", miValueConst2); if (!vwrMiValueTuple.Add(miValueResult2)) return MIstatus::failure; const CMICmnMIValueConst miValueConst3(vrBrkPtInfo.m_fnName); const CMICmnMIValueResult miValueResult3("func", miValueConst3); if (!vwrMiValueTuple.Add(miValueResult3)) return MIstatus::failure; const CMICmnMIValueConst miValueConst5(vrBrkPtInfo.m_fileName); const CMICmnMIValueResult miValueResult5("file", miValueConst5); if (!vwrMiValueTuple.Add(miValueResult5)) return MIstatus::failure; const CMIUtilString strN5 = CMIUtilString::Format("%s/%s", vrBrkPtInfo.m_path.c_str(), vrBrkPtInfo.m_fileName.c_str()); const CMICmnMIValueConst miValueConst6(strN5); const CMICmnMIValueResult miValueResult6("fullname", miValueConst6); if (!vwrMiValueTuple.Add(miValueResult6)) return MIstatus::failure; const CMIUtilString strLine(CMIUtilString::Format("%d", vrBrkPtInfo.m_nLine)); const CMICmnMIValueConst miValueConst7(strLine); const CMICmnMIValueResult miValueResult7("line", miValueConst7); if (!vwrMiValueTuple.Add(miValueResult7)) return MIstatus::failure; 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%08x\", // 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); bool bOk = miValueTuple.Add(miValueResult2); // "disp=" const CMICmnMIValueConst miValueConst3(vrBrkPtInfo.m_bDisp ? "del" : "keep"); const CMICmnMIValueResult miValueResult3("disp", miValueConst3); bOk = bOk && miValueTuple.Add(miValueResult3); // "enabled=" const CMICmnMIValueConst miValueConst4(vrBrkPtInfo.m_bEnabled ? "y" : "n"); const CMICmnMIValueResult miValueResult4("enabled", miValueConst4); bOk = bOk && miValueTuple.Add(miValueResult4); // "addr=" // "func=" // "file=" // "fullname=" // "line=" bOk = bOk && MIResponseFormBrkPtFrameInfo(vrBrkPtInfo, miValueTuple); // "pending=" if (vrBrkPtInfo.m_bPending) { const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strOrigLoc); const CMICmnMIValueList miValueList(miValueConst); const CMICmnMIValueResult miValueResult("pending", miValueList); bOk = bOk && miValueTuple.Add(miValueResult); } if (vrBrkPtInfo.m_bHaveArgOptionThreadGrp) { const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strOptThrdGrp); const CMICmnMIValueList miValueList(miValueConst); const CMICmnMIValueResult miValueResult("thread-groups", miValueList); bOk = bOk && miValueTuple.Add(miValueResult); } // "times=" const CMICmnMIValueConst miValueConstB(CMIUtilString::Format("%d", vrBrkPtInfo.m_nTimes)); const CMICmnMIValueResult miValueResultB("times", miValueConstB); bOk = bOk && miValueTuple.Add(miValueResultB); // "thread=" if (vrBrkPtInfo.m_bBrkPtThreadId) { const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", vrBrkPtInfo.m_nBrkPtThreadId)); const CMICmnMIValueResult miValueResult("thread", miValueConst); bOk = bOk && miValueTuple.Add(miValueResult); } // "cond=" if (vrBrkPtInfo.m_bCondition) { const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strCondition); const CMICmnMIValueResult miValueResult("cond", miValueConst); bOk = bOk && miValueTuple.Add(miValueResult); } // "ignore=" if (vrBrkPtInfo.m_nIgnore != 0) { const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", vrBrkPtInfo.m_nIgnore)); const CMICmnMIValueResult miValueResult("ignore", miValueConst); bOk = bOk && miValueTuple.Add(miValueResult); } // "original-location=" const CMICmnMIValueConst miValueConstC(vrBrkPtInfo.m_strOrigLoc); const CMICmnMIValueResult miValueResultC("original-location", miValueConstC); bOk = bOk && miValueTuple.Add(miValueResultC); vwrMiValueTuple = miValueTuple; return MIstatus::success; } //++ ------------------------------------------------------------------------------------ // Details: Retrieve breakpoint information and write into the given breakpoint information // object. Note not all possible information is retrieved and so the information // object may need to be filled in with more information after calling this // function. Mainly breakpoint location information of information that is // unlikely to change. // Type: Method. // Args: vBrkPt - (R) LLDB break point object. // vrBrkPtInfo - (W) Break point information object. // Return: MIstatus::success - Functional succeeded. // MIstatus::failure - Functional failed. // Throws: None. //-- bool CMICmnLLDBDebugSessionInfo::GetBrkPtInfo(const lldb::SBBreakpoint &vBrkPt, SBrkPtInfo &vrwBrkPtInfo) const { lldb::SBBreakpoint &rBrkPt = const_cast(vBrkPt); lldb::SBBreakpointLocation brkPtLoc = rBrkPt.GetLocationAtIndex(0); lldb::SBAddress brkPtAddr = brkPtLoc.GetAddress(); lldb::SBSymbolContext symbolCntxt = brkPtAddr.GetSymbolContext(lldb::eSymbolContextEverything); const MIchar *pUnkwn = "??"; lldb::SBModule rModule = symbolCntxt.GetModule(); const MIchar *pModule = rModule.IsValid() ? rModule.GetFileSpec().GetFilename() : pUnkwn; MIunused(pModule); const MIchar *pFile = pUnkwn; const MIchar *pFn = pUnkwn; const MIchar *pFilePath = pUnkwn; size_t nLine = 0; const size_t nAddr = brkPtAddr.GetLoadAddress(m_lldbTarget); lldb::SBCompileUnit rCmplUnit = symbolCntxt.GetCompileUnit(); if (rCmplUnit.IsValid()) { lldb::SBFileSpec rFileSpec = rCmplUnit.GetFileSpec(); pFile = rFileSpec.GetFilename(); pFilePath = rFileSpec.GetDirectory(); lldb::SBFunction rFn = symbolCntxt.GetFunction(); if (rFn.IsValid()) pFn = rFn.GetName(); lldb::SBLineEntry rLnEntry = symbolCntxt.GetLineEntry(); if (rLnEntry.GetLine() > 0) nLine = rLnEntry.GetLine(); } vrwBrkPtInfo.m_id = vBrkPt.GetID(); vrwBrkPtInfo.m_strType = "breakpoint"; vrwBrkPtInfo.m_pc = nAddr; vrwBrkPtInfo.m_fnName = pFn; vrwBrkPtInfo.m_fileName = pFile; vrwBrkPtInfo.m_path = pFilePath; vrwBrkPtInfo.m_nLine = nLine; vrwBrkPtInfo.m_nTimes = vBrkPt.GetHitCount(); return MIstatus::success; }