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();
 | |
| }
 |