forked from OSchip/llvm-project
888 lines
34 KiB
C++
888 lines
34 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.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Third party headers:
|
|
#include "lldb/API/SBThread.h"
|
|
#include <inttypes.h> // For PRIx64
|
|
#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 "MICmdData.h"
|
|
#include "MICmnLLDBDebugSessionInfo.h"
|
|
#include "MICmnLLDBDebugger.h"
|
|
#include "MICmnLLDBUtilSBValue.h"
|
|
#include "MICmnMIResultRecord.h"
|
|
#include "MICmnMIValueConst.h"
|
|
#include "MICmnMIValueList.h"
|
|
#include "MICmnMIValueTuple.h"
|
|
#include "MICmnResources.h"
|
|
#include "Platform.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);
|
|
// If one stops inside try block with, which catch clause type is unnamed
|
|
// (e.g std::exception&) then value name will be nullptr as well as value
|
|
// pointer
|
|
const char *name = value.GetName();
|
|
if (name == nullptr)
|
|
continue;
|
|
const CMICmnMIValueConst miValueConst(name);
|
|
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[PATH_MAX];
|
|
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();
|
|
}
|