| //===-- MICmnLLDBDebugSessionInfo.cpp ---------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| // Third party headers: |
| #include <inttypes.h> // For PRIx64 |
| #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() |
| : m_nBrkPointCntMax(INT32_MAX) |
| , m_currentSelectedThread(LLDB_INVALID_THREAD_ID) |
| , m_constStrSharedDataKeyWkDir("Working Directory") |
| , m_constStrSharedDataSolibPath("Solib Path") |
| , m_constStrPrintCharArrayAsString("Print CharArrayAsString") |
| , m_constStrPrintExpandAggregates("Print ExpandAggregates") |
| , m_constStrPrintAggregateFieldNames("Print AggregateFieldNames") |
| { |
| } |
| |
| //++ ------------------------------------------------------------------------------------ |
| // Details: CMICmnLLDBDebugSessionInfo destructor. |
| // Type: Overridable. |
| // Args: None. |
| // Return: None. |
| // Throws: None. |
| //-- |
| CMICmnLLDBDebugSessionInfo::~CMICmnLLDBDebugSessionInfo() |
| { |
| 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() |
| { |
| 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() |
| { |
| if (--m_clientUsageRefCnt > 0) |
| return MIstatus::success; |
| |
| if (!m_bInitialized) |
| return MIstatus::success; |
| |
| // Tidy up |
| SharedDataDestroy(); |
| |
| 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: None. |
| // Throws: None. |
| //-- |
| void |
| CMICmnLLDBDebugSessionInfo::SharedDataDestroy() |
| { |
| m_mapIdToSessionData.Clear(); |
| m_vecVarObj.clear(); |
| m_mapBrkPtIdToBrkPtInfo.clear(); |
| } |
| |
| //++ ------------------------------------------------------------------------------------ |
| // 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, const FrameInfoFormat_e veFrameInfoFormat, |
| CMIUtilString &vwrThreadFrames) |
| { |
| lldb::SBThread thread = GetProcess().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%016" PRIx64 "\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"},frame={level=\"%d\",addr=\"0x%016" PRIx64 "\",func=\"%s\",args=[%s],file=\"%s\",fullname=\"%s\",line=\"%d\"}, |
| // ..." |
| CMIUtilString strListCommaSeparated; |
| for (MIuint nLevel = 0; nLevel < nFrames; nLevel++) |
| { |
| CMICmnMIValueTuple miValueTuple; |
| if (!MIResponseFormFrameInfo(thread, nLevel, veFrameInfoFormat, miValueTuple)) |
| return MIstatus::failure; |
| |
| const CMICmnMIValueResult miValueResult2("frame", miValueTuple); |
| if (nLevel != 0) |
| strListCommaSeparated += ","; |
| strListCommaSeparated += miValueResult2.GetString(); |
| } |
| |
| vwrThreadFrames = strListCommaSeparated; |
| |
| 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, |
| const ThreadInfoFormat_e veThreadInfoFormat, 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); |
| vwrMIValueTuple.Add(miValueResult1); |
| |
| // Add "target-id" |
| const char *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 arbitrary number |
| const char *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); |
| vwrMIValueTuple.Add(miValueResult2); |
| |
| // Add "frame" |
| if (veThreadInfoFormat != eThreadInfoFormat_NoFrames) |
| { |
| CMIUtilString strFrames; |
| if (!GetThreadFrames(vCmdData, rThread.GetIndexID(), eFrameInfoFormat_AllArgumentsInSimpleForm, strFrames)) |
| return MIstatus::failure; |
| |
| const CMICmnMIValueConst miValueConst3(strFrames, true); |
| vwrMIValueTuple.Add(miValueConst3, false); |
| } |
| |
| // Add "state" |
| const CMICmnMIValueConst miValueConst4(strState); |
| const CMICmnMIValueResult miValueResult4("state", miValueConst4); |
| vwrMIValueTuple.Add(miValueResult4); |
| |
| return MIstatus::success; |
| } |
| |
| //++ ------------------------------------------------------------------------------------ |
| // Details: Form MI partial response by appending more MI value type objects to the |
| // tuple type object past in. |
| // Type: Method. |
| // Args: vrFrame - (R) LLDB thread object. |
| // vMaskVarTypes - (R) Construed according to VariableType_e. |
| // veVarInfoFormat - (R) The type of variable info that should be shown. |
| // 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, |
| const VariableInfoFormat_e veVarInfoFormat, CMICmnMIValueList &vwrMiValueList, |
| const MIuint vnMaxDepth, /* = 10 */ |
| const bool vbMarkArgs /* = false*/) |
| { |
| 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); |
| |
| // Handle arguments first |
| lldb::SBValueList listArg = rFrame.GetVariables(bArg, false, false, false); |
| bOk = bOk && MIResponseForVariableInfoInternal(veVarInfoFormat, vwrMiValueList, listArg, vnMaxDepth, true, vbMarkArgs); |
| |
| // Handle remaining variables |
| lldb::SBValueList listVars = rFrame.GetVariables(false, bLocals, bStatics, bInScopeOnly); |
| bOk = bOk && MIResponseForVariableInfoInternal(veVarInfoFormat, vwrMiValueList, listVars, vnMaxDepth, false, vbMarkArgs); |
| |
| return bOk; |
| } |
| |
| bool |
| CMICmnLLDBDebugSessionInfo::MIResponseForVariableInfoInternal(const VariableInfoFormat_e veVarInfoFormat, |
| CMICmnMIValueList &vwrMiValueList, |
| const lldb::SBValueList &vwrSBValueList, |
| const MIuint vnMaxDepth, |
| const bool vbIsArgs, |
| const bool vbMarkArgs) |
| { |
| const MIuint nArgs = vwrSBValueList.GetSize(); |
| for (MIuint i = 0; i < nArgs; i++) |
| { |
| CMICmnMIValueTuple miValueTuple; |
| lldb::SBValue value = vwrSBValueList.GetValueAtIndex(i); |
| const CMICmnMIValueConst miValueConst(value.GetName()); |
| const CMICmnMIValueResult miValueResultName("name", miValueConst); |
| if (vbMarkArgs && vbIsArgs) |
| { |
| const CMICmnMIValueConst miValueConstArg("1"); |
| const CMICmnMIValueResult miValueResultArg("arg", miValueConstArg); |
| miValueTuple.Add(miValueResultArg); |
| } |
| if (veVarInfoFormat != eVariableInfoFormat_NoValues) |
| { |
| miValueTuple.Add(miValueResultName); // name |
| if (veVarInfoFormat == eVariableInfoFormat_SimpleValues) |
| { |
| const CMICmnMIValueConst miValueConst3(value.GetTypeName()); |
| const CMICmnMIValueResult miValueResult3("type", miValueConst3); |
| miValueTuple.Add(miValueResult3); |
| } |
| const MIuint nChildren = value.GetNumChildren(); |
| const bool bIsPointerType = value.GetType().IsPointerType(); |
| if (nChildren == 0 || // no children |
| (bIsPointerType && nChildren == 1) || // pointers |
| veVarInfoFormat == eVariableInfoFormat_AllValues) // show all values |
| { |
| CMIUtilString strValue; |
| if (GetVariableInfo(value, vnMaxDepth == 0, strValue)) |
| { |
| const CMICmnMIValueConst miValueConst2(strValue.Escape().AddSlashes()); |
| const CMICmnMIValueResult miValueResult2("value", miValueConst2); |
| miValueTuple.Add(miValueResult2); |
| } |
| } |
| vwrMiValueList.Add(miValueTuple); |
| continue; |
| } |
| |
| if (vbMarkArgs) |
| { |
| // If we are printing names only with vbMarkArgs, we still need to add the name to the value tuple |
| miValueTuple.Add(miValueResultName); // name |
| vwrMiValueList.Add(miValueTuple); |
| } |
| else |
| { |
| // If we are printing name only then no need to put it in the tuple. |
| vwrMiValueList.Add(miValueResultName); |
| } |
| } |
| return MIstatus::success; |
| } |
| |
| //++ ------------------------------------------------------------------------------------ |
| // Details: Extract the value's name and value or recurse into child value object. |
| // Type: Method. |
| // Args: vrValue - (R) LLDB value object. |
| // vbInSimpleForm - (R) True = Get variable info in simple form (i.e. don't expand aggregates). |
| // - False = Get variable info (and expand aggregates if any). |
| // vwrStrValue t - (W) The string representation of this value. |
| // Return: MIstatus::success - Functional succeeded. |
| // MIstatus::failure - Functional failed. |
| // Throws: None. |
| //-- |
| bool |
| CMICmnLLDBDebugSessionInfo::GetVariableInfo(const lldb::SBValue &vrValue, const bool vbInSimpleForm, CMIUtilString &vwrStrValue) |
| { |
| const CMICmnLLDBUtilSBValue utilValue(vrValue, true, false); |
| const bool bExpandAggregates = vbInSimpleForm ? false : true; |
| vwrStrValue = utilValue.GetValue(bExpandAggregates); |
| 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: vrThread - (R) LLDB thread object. |
| // vwrMIValueTuple - (W) MI value tuple object. |
| // vArgInfo - (R) Args information in MI response form. |
| // Return: MIstatus::success - Functional succeeded. |
| // MIstatus::failure - Functional failed. |
| // Throws: None. |
| //-- |
| bool |
| CMICmnLLDBDebugSessionInfo::MIResponseFormFrameInfo(const lldb::SBThread &vrThread, const MIuint vnLevel, |
| const FrameInfoFormat_e veFrameInfoFormat, 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%016" PRIx64 "\",func=\"%s\",file=\"%s\",fullname=\"%s\",line=\"%d\"}" |
| const CMIUtilString strLevel(CMIUtilString::Format("%d", vnLevel)); |
| const CMICmnMIValueConst miValueConst(strLevel); |
| const CMICmnMIValueResult miValueResult("level", miValueConst); |
| vwrMiValueTuple.Add(miValueResult); |
| const CMIUtilString strAddr(CMIUtilString::Format("0x%016" PRIx64, pc)); |
| const CMICmnMIValueConst miValueConst2(strAddr); |
| const CMICmnMIValueResult miValueResult2("addr", miValueConst2); |
| vwrMiValueTuple.Add(miValueResult2); |
| const CMICmnMIValueConst miValueConst3(fnName); |
| const CMICmnMIValueResult miValueResult3("func", miValueConst3); |
| vwrMiValueTuple.Add(miValueResult3); |
| if (veFrameInfoFormat != eFrameInfoFormat_NoArguments) |
| { |
| CMICmnMIValueList miValueList(true); |
| const MIuint maskVarTypes = eVariableType_Arguments; |
| if (veFrameInfoFormat == eFrameInfoFormat_AllArgumentsInSimpleForm) |
| { |
| if (!MIResponseFormVariableInfo(frame, maskVarTypes, eVariableInfoFormat_AllValues, miValueList, 0)) |
| return MIstatus::failure; |
| } |
| else |
| if (!MIResponseFormVariableInfo(frame, maskVarTypes, eVariableInfoFormat_AllValues, miValueList)) |
| return MIstatus::failure; |
| |
| const CMICmnMIValueResult miValueResult4("args", miValueList); |
| vwrMiValueTuple.Add(miValueResult4); |
| } |
| const CMICmnMIValueConst miValueConst5(fileName); |
| const CMICmnMIValueResult miValueResult5("file", miValueConst5); |
| vwrMiValueTuple.Add(miValueResult5); |
| const CMICmnMIValueConst miValueConst6(path); |
| const CMICmnMIValueResult miValueResult6("fullname", miValueConst6); |
| vwrMiValueTuple.Add(miValueResult6); |
| const CMIUtilString strLine(CMIUtilString::Format("%d", nLine)); |
| const CMICmnMIValueConst miValueConst7(strLine); |
| const CMICmnMIValueResult miValueResult7("line", miValueConst7); |
| vwrMiValueTuple.Add(miValueResult7); |
| |
| 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 char *pUnkwn = "??"; |
| if (!ResolvePath(pUnkwn, strResolvedPath)) |
| return MIstatus::failure; |
| vwPath = strResolvedPath; |
| |
| vwPc = rFrame.GetPC(); |
| |
| const char *pFnName = rFrame.GetFunctionName(); |
| vwFnName = (pFnName != nullptr) ? pFnName : pUnkwn; |
| |
| const char *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: vrBrkPtInfo - (R) Break point information object. |
| // vwrMIValueTuple - (W) MI value tuple object. |
| // Return: None. |
| // Throws: None. |
| //-- |
| void |
| CMICmnLLDBDebugSessionInfo::MIResponseFormBrkPtFrameInfo(const SBrkPtInfo &vrBrkPtInfo, CMICmnMIValueTuple &vwrMiValueTuple) |
| { |
| const CMIUtilString strAddr(CMIUtilString::Format("0x%016" PRIx64, vrBrkPtInfo.m_pc)); |
| const CMICmnMIValueConst miValueConst2(strAddr); |
| const CMICmnMIValueResult miValueResult2("addr", miValueConst2); |
| vwrMiValueTuple.Add(miValueResult2); |
| const CMICmnMIValueConst miValueConst3(vrBrkPtInfo.m_fnName); |
| const CMICmnMIValueResult miValueResult3("func", miValueConst3); |
| vwrMiValueTuple.Add(miValueResult3); |
| const CMICmnMIValueConst miValueConst5(vrBrkPtInfo.m_fileName); |
| const CMICmnMIValueResult miValueResult5("file", miValueConst5); |
| vwrMiValueTuple.Add(miValueResult5); |
| 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); |
| vwrMiValueTuple.Add(miValueResult6); |
| const CMIUtilString strLine(CMIUtilString::Format("%d", vrBrkPtInfo.m_nLine)); |
| const CMICmnMIValueConst miValueConst7(strLine); |
| const CMICmnMIValueResult miValueResult7("line", miValueConst7); |
| vwrMiValueTuple.Add(miValueResult7); |
| } |
| |
| //++ ------------------------------------------------------------------------------------ |
| // Details: Form MI partial response by appending more MI value type objects to the |
| // tuple type object past in. |
| // Type: Method. |
| // Args: vrBrkPtInfo - (R) Break point information object. |
| // vwrMIValueTuple - (W) MI value tuple object. |
| // Return: MIstatus::success - Functional succeeded. |
| // MIstatus::failure - Functional failed. |
| // Throws: None. |
| //-- |
| bool |
| CMICmnLLDBDebugSessionInfo::MIResponseFormBrkPtInfo(const SBrkPtInfo &vrBrkPtInfo, CMICmnMIValueTuple &vwrMiValueTuple) |
| { |
| // MI print "=breakpoint-modified,bkpt={number=\"%d\",type=\"breakpoint\",disp=\"%s\",enabled=\"%c\",addr=\"0x%016" PRIx64 "\", |
| // func=\"%s\",file=\"%s\",fullname=\"%s/%s\",line=\"%d\",times=\"%d\",original-location=\"%s\"}" |
| |
| // "number=" |
| const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", vrBrkPtInfo.m_id)); |
| const CMICmnMIValueResult miValueResult("number", miValueConst); |
| CMICmnMIValueTuple miValueTuple(miValueResult); |
| // "type=" |
| const CMICmnMIValueConst miValueConst2(vrBrkPtInfo.m_strType); |
| const CMICmnMIValueResult miValueResult2("type", miValueConst2); |
| miValueTuple.Add(miValueResult2); |
| // "disp=" |
| const CMICmnMIValueConst miValueConst3(vrBrkPtInfo.m_bDisp ? "del" : "keep"); |
| const CMICmnMIValueResult miValueResult3("disp", miValueConst3); |
| miValueTuple.Add(miValueResult3); |
| // "enabled=" |
| const CMICmnMIValueConst miValueConst4(vrBrkPtInfo.m_bEnabled ? "y" : "n"); |
| const CMICmnMIValueResult miValueResult4("enabled", miValueConst4); |
| miValueTuple.Add(miValueResult4); |
| // "addr=" |
| // "func=" |
| // "file=" |
| // "fullname=" |
| // "line=" |
| MIResponseFormBrkPtFrameInfo(vrBrkPtInfo, miValueTuple); |
| // "pending=" |
| if (vrBrkPtInfo.m_bPending) |
| { |
| const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strOrigLoc); |
| const CMICmnMIValueList miValueList(miValueConst); |
| const CMICmnMIValueResult miValueResult("pending", miValueList); |
| miValueTuple.Add(miValueResult); |
| } |
| if (vrBrkPtInfo.m_bHaveArgOptionThreadGrp) |
| { |
| const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strOptThrdGrp); |
| const CMICmnMIValueList miValueList(miValueConst); |
| const CMICmnMIValueResult miValueResult("thread-groups", miValueList); |
| miValueTuple.Add(miValueResult); |
| } |
| // "times=" |
| const CMICmnMIValueConst miValueConstB(CMIUtilString::Format("%d", vrBrkPtInfo.m_nTimes)); |
| const CMICmnMIValueResult miValueResultB("times", miValueConstB); |
| miValueTuple.Add(miValueResultB); |
| // "thread=" |
| if (vrBrkPtInfo.m_bBrkPtThreadId) |
| { |
| const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", vrBrkPtInfo.m_nBrkPtThreadId)); |
| const CMICmnMIValueResult miValueResult("thread", miValueConst); |
| miValueTuple.Add(miValueResult); |
| } |
| // "cond=" |
| if (vrBrkPtInfo.m_bCondition) |
| { |
| const CMICmnMIValueConst miValueConst(vrBrkPtInfo.m_strCondition); |
| const CMICmnMIValueResult miValueResult("cond", miValueConst); |
| miValueTuple.Add(miValueResult); |
| } |
| // "ignore=" |
| if (vrBrkPtInfo.m_nIgnore != 0) |
| { |
| const CMICmnMIValueConst miValueConst(CMIUtilString::Format("%d", vrBrkPtInfo.m_nIgnore)); |
| const CMICmnMIValueResult miValueResult("ignore", miValueConst); |
| miValueTuple.Add(miValueResult); |
| } |
| // "original-location=" |
| const CMICmnMIValueConst miValueConstC(vrBrkPtInfo.m_strOrigLoc); |
| const CMICmnMIValueResult miValueResultC("original-location", miValueConstC); |
| miValueTuple.Add(miValueResultC); |
| |
| vwrMiValueTuple = miValueTuple; |
| |
| return MIstatus::success; |
| } |
| |
| //++ ------------------------------------------------------------------------------------ |
| // 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 char *pUnkwn = "??"; |
| lldb::SBModule rModule = symbolCntxt.GetModule(); |
| const char *pModule = rModule.IsValid() ? rModule.GetFileSpec().GetFilename() : pUnkwn; |
| MIunused(pModule); |
| const char *pFile = pUnkwn; |
| const char *pFn = pUnkwn; |
| const char *pFilePath = pUnkwn; |
| size_t nLine = 0; |
| lldb::addr_t nAddr = brkPtAddr.GetLoadAddress(GetTarget()); |
| if (nAddr == LLDB_INVALID_ADDRESS) |
| nAddr = brkPtAddr.GetFileAddress(); |
| |
| 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; |
| } |
| |
| //++ ------------------------------------------------------------------------------------ |
| // Details: Get current debugger. |
| // Type: Method. |
| // Args: None. |
| // Return: lldb::SBDebugger - current debugger. |
| // Throws: None. |
| //-- |
| lldb::SBDebugger & |
| CMICmnLLDBDebugSessionInfo::GetDebugger() const |
| { |
| return CMICmnLLDBDebugger::Instance().GetTheDebugger(); |
| } |
| |
| //++ ------------------------------------------------------------------------------------ |
| // Details: Get current listener. |
| // Type: Method. |
| // Args: None. |
| // Return: lldb::SBListener - current listener. |
| // Throws: None. |
| //-- |
| lldb::SBListener & |
| CMICmnLLDBDebugSessionInfo::GetListener() const |
| { |
| return CMICmnLLDBDebugger::Instance().GetTheListener(); |
| } |
| |
| //++ ------------------------------------------------------------------------------------ |
| // Details: Get current target. |
| // Type: Method. |
| // Args: None. |
| // Return: lldb::SBTarget - current target. |
| // Throws: None. |
| //-- |
| lldb::SBTarget |
| CMICmnLLDBDebugSessionInfo::GetTarget() const |
| { |
| return GetDebugger().GetSelectedTarget(); |
| } |
| |
| //++ ------------------------------------------------------------------------------------ |
| // Details: Get current process. |
| // Type: Method. |
| // Args: None. |
| // Return: lldb::SBProcess - current process. |
| // Throws: None. |
| //-- |
| lldb::SBProcess |
| CMICmnLLDBDebugSessionInfo::GetProcess() const |
| { |
| return GetTarget().GetProcess(); |
| } |