| //===-- 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 <lldb/API/SBThread.h> |
| #ifdef _WIN32 |
| #include <io.h> // For the ::_access() |
| #else |
| #include <unistd.h> // For the ::access() |
| #endif // _WIN32 |
| #include <lldb/API/SBBreakpointLocation.h> |
| |
| // 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<CMIUtilString>(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<lldb::SBThread &>(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<lldb::SBThread &>(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<lldb::SBThread &>(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<lldb::SBFrame &>(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<lldb::SBFrame &>(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<lldb::SBFrame &>(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<lldb::SBValue &>(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<lldb::SBValue &>(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<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; |
| |
| // 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<lldb::SBFrame &>(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<lldb::SBBreakpoint &>(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; |
| } |