llvm-project/lldb/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp

1528 lines
63 KiB
C++

//===-- 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_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 = 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%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, eVariableInfoFormat_AllValues, 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 = 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%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, eVariableInfoFormat_AllValues, 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.
// 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::MIResponseFormVariableInfo2(const lldb::SBFrame &vrFrame, const MIuint vMaskVarTypes,
const VariableInfoFormat_e veVarInfoFormat, 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.
// 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)
{
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, veVarInfoFormat, 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.
// 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::MIResponseFormVariableInfo3(const lldb::SBFrame &vrFrame, const MIuint vMaskVarTypes,
const VariableInfoFormat_e veVarInfoFormat, 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, veVarInfoFormat, 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.
// veVarInfoFormat - (R) The type of variable info that should be shown.
// 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,
const VariableInfoFormat_e veVarInfoFormat, 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
switch (veVarInfoFormat)
{
case eVariableInfoFormat_NoValues:
{
const CMICmnMIValueConst miValueConst(utilValue.GetName());
const CMICmnMIValueResult miValueResult("name", miValueConst);
return vwrMiValueList.Add(miValueResult);
}
case eVariableInfoFormat_AllValues:
case eVariableInfoFormat_SimpleValues:
{
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);
break;
}
default:
break;
}
return vwrMiValueList.Add(miValueTuple);
}
}
else if (bIsPointerType && utilValue.IsChildCharType())
{
switch (veVarInfoFormat)
{
case eVariableInfoFormat_NoValues:
{
const CMICmnMIValueConst miValueConst(utilValue.GetName());
const CMICmnMIValueResult miValueResult("name", miValueConst);
return vwrMiValueList.Add(miValueResult);
}
case eVariableInfoFormat_AllValues:
case eVariableInfoFormat_SimpleValues:
{
// 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);
}
}
break;
}
default:
break;
}
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
switch (veVarInfoFormat)
{
case eVariableInfoFormat_NoValues:
{
const CMICmnMIValueConst miValueConst(utilValue.GetName());
const CMICmnMIValueResult miValueResult("name", miValueConst);
return vwrMiValueList.Add(miValueResult);
}
case eVariableInfoFormat_AllValues:
case eVariableInfoFormat_SimpleValues:
{
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);
break;
}
default:
break;
}
return vwrMiValueList.Add(miValueTuple);
}
}
else
{
switch (veVarInfoFormat)
{
case eVariableInfoFormat_NoValues:
{
const CMICmnMIValueConst miValueConst(utilValue.GetName());
const CMICmnMIValueResult miValueResult("name", miValueConst);
return vwrMiValueList.Add(miValueResult);
}
case eVariableInfoFormat_AllValues:
case eVariableInfoFormat_SimpleValues:
{
// 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, veVarInfoFormat, 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);
break;
}
default:
break;
}
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.
// veVarInfoFormat - (R) The type of variable info that should be shown.
// 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,
const VariableInfoFormat_e veVarInfoFormat, 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
switch (veVarInfoFormat)
{
case eVariableInfoFormat_NoValues:
{
const CMICmnMIValueConst miValueConst(utilValue.GetName());
const CMICmnMIValueResult miValueResult("name", miValueConst);
return vwrMiValueList.Add(miValueResult);
}
case eVariableInfoFormat_AllValues:
case eVariableInfoFormat_SimpleValues:
{
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);
break;
}
default:
break;
}
return vwrMiValueList.Add(miValueTuple);
}
}
else if (utilValue.IsChildCharType())
{
switch (veVarInfoFormat)
{
case eVariableInfoFormat_NoValues:
{
const CMICmnMIValueConst miValueConst(utilValue.GetName());
const CMICmnMIValueResult miValueResult("name", miValueConst);
return vwrMiValueList.Add(miValueResult);
}
case eVariableInfoFormat_AllValues:
case eVariableInfoFormat_SimpleValues:
{
// 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);
}
}
break;
}
default:
break;
}
return vwrMiValueList.Add(miValueTuple);
}
else
{
switch (veVarInfoFormat)
{
case eVariableInfoFormat_NoValues:
{
const CMICmnMIValueConst miValueConst(utilValue.GetName());
const CMICmnMIValueResult miValueResult("name", miValueConst);
return vwrMiValueList.Add(miValueResult);
}
case eVariableInfoFormat_AllValues:
case eVariableInfoFormat_SimpleValues:
{
// 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, veVarInfoFormat, 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);
break;
}
default:
break;
}
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(GetTarget());
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();
}