forked from OSchip/llvm-project
1611 lines
64 KiB
C++
1611 lines
64 KiB
C++
//===-- MICmnLLDBDebuggerHandleEvents.cpp --------------------------------------------*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//++
|
|
// File: MICmnLLDBDebuggerHandleEvents.cpp
|
|
//
|
|
// Overview: CMICmnLLDBDebuggerHandleEvents 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/SBEvent.h"
|
|
#include "lldb/API/SBProcess.h"
|
|
#include "lldb/API/SBBreakpoint.h"
|
|
#include "lldb/API/SBStream.h"
|
|
#include "lldb/API/SBThread.h"
|
|
#include "lldb/API/SBCommandInterpreter.h"
|
|
#include "lldb/API/SBCommandReturnObject.h"
|
|
#ifdef _WIN32
|
|
#include <io.h> // For the ::_access()
|
|
#else
|
|
#include <unistd.h> // For the ::access()
|
|
#endif // _WIN32
|
|
#include <limits.h>
|
|
|
|
// In-house headers:
|
|
#include "MICmnLLDBDebuggerHandleEvents.h"
|
|
#include "MICmnResources.h"
|
|
#include "MICmnLog.h"
|
|
#include "MICmnLLDBDebugSessionInfo.h"
|
|
#include "MICmnMIResultRecord.h"
|
|
#include "MICmnMIValueConst.h"
|
|
#include "MICmnMIValueList.h"
|
|
#include "MICmnMIOutOfBandRecord.h"
|
|
#include "MICmnStreamStdout.h"
|
|
#include "MICmnStreamStderr.h"
|
|
#include "MIUtilDebug.h"
|
|
#include "MIDriver.h"
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: CMICmnLLDBDebuggerHandleEvents constructor.
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: None.
|
|
// Throws: None.
|
|
//--
|
|
CMICmnLLDBDebuggerHandleEvents::CMICmnLLDBDebuggerHandleEvents(void)
|
|
{
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: CMICmnLLDBDebuggerHandleEvents destructor.
|
|
// Type: Overridable.
|
|
// Args: None.
|
|
// Return: None.
|
|
// Throws: None.
|
|
//--
|
|
CMICmnLLDBDebuggerHandleEvents::~CMICmnLLDBDebuggerHandleEvents(void)
|
|
{
|
|
Shutdown();
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Initialize resources for *this broardcaster object.
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::Initialize(void)
|
|
{
|
|
m_clientUsageRefCnt++;
|
|
|
|
if (m_bInitialized)
|
|
return MIstatus::success;
|
|
|
|
m_bInitialized = MIstatus::success;
|
|
|
|
return m_bInitialized;
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Release resources for *this broardcaster object.
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::Shutdown(void)
|
|
{
|
|
if (--m_clientUsageRefCnt > 0)
|
|
return MIstatus::success;
|
|
|
|
if (!m_bInitialized)
|
|
return MIstatus::success;
|
|
|
|
m_bInitialized = false;
|
|
|
|
return MIstatus::success;
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Interpret the event object to asscertain the action to take or information to
|
|
// to form and put in a MI Out-of-band record object which is given to stdout.
|
|
// Type: Method.
|
|
// Args: vEvent - (R) An LLDB broadcast event.
|
|
// vrbHandledEvent - (W) True - event handled, false = not handled.
|
|
// vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::HandleEvent(const lldb::SBEvent &vEvent, bool &vrbHandledEvent, bool &vrbExitAppEvent)
|
|
{
|
|
bool bOk = MIstatus::success;
|
|
vrbHandledEvent = false;
|
|
vrbExitAppEvent = false;
|
|
|
|
if (lldb::SBProcess::EventIsProcessEvent(vEvent))
|
|
{
|
|
vrbHandledEvent = true;
|
|
bOk = HandleEventSBProcess(vEvent, vrbExitAppEvent);
|
|
}
|
|
else if (lldb::SBBreakpoint::EventIsBreakpointEvent(vEvent))
|
|
{
|
|
vrbHandledEvent = true;
|
|
bOk = HandleEventSBBreakPoint(vEvent);
|
|
}
|
|
else if (lldb::SBThread::EventIsThreadEvent(vEvent))
|
|
{
|
|
vrbHandledEvent = true;
|
|
bOk = HandleEventSBThread(vEvent);
|
|
}
|
|
|
|
return bOk;
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Handle a LLDB SBProcess event.
|
|
// Type: Method.
|
|
// Args: vEvent - (R) An LLDB broadcast event.
|
|
// vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::HandleEventSBProcess(const lldb::SBEvent &vEvent, bool &vrbExitAppEvent)
|
|
{
|
|
bool bOk = MIstatus::success;
|
|
|
|
const MIchar *pEventType = "";
|
|
const MIuint nEventType = vEvent.GetType();
|
|
switch (nEventType)
|
|
{
|
|
case lldb::SBProcess::eBroadcastBitInterrupt:
|
|
pEventType = "eBroadcastBitInterrupt";
|
|
break;
|
|
case lldb::SBProcess::eBroadcastBitProfileData:
|
|
pEventType = "eBroadcastBitProfileData";
|
|
break;
|
|
case lldb::SBProcess::eBroadcastBitStateChanged:
|
|
pEventType = "eBroadcastBitStateChanged";
|
|
bOk = HandleProcessEventBroadcastBitStateChanged(vEvent, vrbExitAppEvent);
|
|
break;
|
|
case lldb::SBProcess::eBroadcastBitSTDERR:
|
|
pEventType = "eBroadcastBitSTDERR";
|
|
bOk = GetProcessStderr();
|
|
break;
|
|
case lldb::SBProcess::eBroadcastBitSTDOUT:
|
|
pEventType = "eBroadcastBitSTDOUT";
|
|
bOk = GetProcessStdout();
|
|
break;
|
|
default:
|
|
{
|
|
const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBProcess", (MIuint)nEventType));
|
|
SetErrorDescription(msg);
|
|
return MIstatus::failure;
|
|
}
|
|
}
|
|
m_pLog->WriteLog(CMIUtilString::Format("##### An SB Process event occurred: %s", pEventType));
|
|
|
|
return bOk;
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Handle a LLDB SBBreakpoint event.
|
|
// Type: Method.
|
|
// Args: vEvent - (R) An LLDB broadcast event.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakPoint(const lldb::SBEvent &vEvent)
|
|
{
|
|
bool bOk = MIstatus::success;
|
|
|
|
const MIchar *pEventType = "";
|
|
const lldb::BreakpointEventType eEvent = lldb::SBBreakpoint::GetBreakpointEventTypeFromEvent(vEvent);
|
|
switch (eEvent)
|
|
{
|
|
case lldb::eBreakpointEventTypeThreadChanged:
|
|
pEventType = "eBreakpointEventTypeThreadChanged";
|
|
break;
|
|
case lldb::eBreakpointEventTypeLocationsRemoved:
|
|
pEventType = "eBreakpointEventTypeLocationsRemoved";
|
|
break;
|
|
case lldb::eBreakpointEventTypeInvalidType:
|
|
pEventType = "eBreakpointEventTypeInvalidType";
|
|
break;
|
|
case lldb::eBreakpointEventTypeLocationsAdded:
|
|
pEventType = "eBreakpointEventTypeLocationsAdded";
|
|
bOk = HandleEventSBBreakpointLocationsAdded(vEvent);
|
|
break;
|
|
case lldb::eBreakpointEventTypeAdded:
|
|
pEventType = "eBreakpointEventTypeAdded";
|
|
bOk = HandleEventSBBreakpointAdded(vEvent);
|
|
break;
|
|
case lldb::eBreakpointEventTypeRemoved:
|
|
pEventType = "eBreakpointEventTypeRemoved";
|
|
bOk = HandleEventSBBreakpointCmn(vEvent);
|
|
break;
|
|
case lldb::eBreakpointEventTypeLocationsResolved:
|
|
pEventType = "eBreakpointEventTypeLocationsResolved";
|
|
break;
|
|
case lldb::eBreakpointEventTypeEnabled:
|
|
pEventType = "eBreakpointEventTypeEnabled";
|
|
bOk = HandleEventSBBreakpointCmn(vEvent);
|
|
break;
|
|
case lldb::eBreakpointEventTypeDisabled:
|
|
pEventType = "eBreakpointEventTypeDisabled";
|
|
bOk = HandleEventSBBreakpointCmn(vEvent);
|
|
break;
|
|
case lldb::eBreakpointEventTypeCommandChanged:
|
|
pEventType = "eBreakpointEventTypeCommandChanged";
|
|
bOk = HandleEventSBBreakpointCmn(vEvent);
|
|
break;
|
|
case lldb::eBreakpointEventTypeConditionChanged:
|
|
pEventType = "eBreakpointEventTypeConditionChanged";
|
|
bOk = HandleEventSBBreakpointCmn(vEvent);
|
|
break;
|
|
case lldb::eBreakpointEventTypeIgnoreChanged:
|
|
pEventType = "eBreakpointEventTypeIgnoreChanged";
|
|
bOk = HandleEventSBBreakpointCmn(vEvent);
|
|
break;
|
|
}
|
|
m_pLog->WriteLog(CMIUtilString::Format("##### An SB Breakpoint event occurred: %s", pEventType));
|
|
|
|
return bOk;
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Handle a LLDB SBBreakpoint event.
|
|
// Type: Method.
|
|
// Args: vEvent - (R) An LLDB broadcast event.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointLocationsAdded(const lldb::SBEvent &vEvent)
|
|
{
|
|
const MIuint nLoc = lldb::SBBreakpoint::GetNumBreakpointLocationsFromEvent(vEvent);
|
|
if (nLoc == 0)
|
|
return MIstatus::success;
|
|
|
|
lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent(vEvent);
|
|
const CMIUtilString plural((nLoc == 1) ? "" : "s");
|
|
const CMIUtilString msg(CMIUtilString::Format("%d location%s added to breakpoint %d", nLoc, plural.c_str(), brkPt.GetID()));
|
|
|
|
return TextToStdout(msg);
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Handle a LLDB SBBreakpoint event.
|
|
// Type: Method.
|
|
// Args: vEvent - (R) An LLDB broadcast event.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointCmn(const lldb::SBEvent &vEvent)
|
|
{
|
|
lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent(vEvent);
|
|
if (!brkPt.IsValid())
|
|
return MIstatus::success;
|
|
|
|
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
|
|
CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
|
|
if (!rSessionInfo.GetBrkPtInfo(brkPt, sBrkPtInfo))
|
|
{
|
|
SetErrorDescription(
|
|
CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET), "HandleEventSBBreakpointCmn()", brkPt.GetID()));
|
|
return MIstatus::failure;
|
|
}
|
|
|
|
// CODETAG_LLDB_BREAKPOINT_CREATION
|
|
// This is in a worker thread
|
|
// Add more breakpoint information or overwrite existing information
|
|
CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfoRec;
|
|
if (!rSessionInfo.RecordBrkPtInfoGet(brkPt.GetID(), sBrkPtInfoRec))
|
|
{
|
|
SetErrorDescription(
|
|
CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_NOTFOUND), "HandleEventSBBreakpointCmn()", brkPt.GetID()));
|
|
return MIstatus::failure;
|
|
}
|
|
sBrkPtInfo.m_bDisp = sBrkPtInfoRec.m_bDisp;
|
|
sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
|
|
sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
|
|
sBrkPtInfo.m_strOptThrdGrp = "";
|
|
sBrkPtInfo.m_nTimes = brkPt.GetHitCount();
|
|
sBrkPtInfo.m_strOrigLoc = sBrkPtInfoRec.m_strOrigLoc;
|
|
sBrkPtInfo.m_nIgnore = sBrkPtInfoRec.m_nIgnore;
|
|
sBrkPtInfo.m_bPending = sBrkPtInfoRec.m_bPending;
|
|
sBrkPtInfo.m_bCondition = sBrkPtInfoRec.m_bCondition;
|
|
sBrkPtInfo.m_strCondition = sBrkPtInfoRec.m_strCondition;
|
|
sBrkPtInfo.m_bBrkPtThreadId = sBrkPtInfoRec.m_bBrkPtThreadId;
|
|
sBrkPtInfo.m_nBrkPtThreadId = sBrkPtInfoRec.m_nBrkPtThreadId;
|
|
|
|
// 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\"}"
|
|
CMICmnMIValueTuple miValueTuple;
|
|
if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple))
|
|
{
|
|
SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE), "HandleEventSBBreakpointCmn()"));
|
|
return MIstatus::failure;
|
|
}
|
|
|
|
const CMICmnMIValueResult miValueResultC("bkpt", miValueTuple);
|
|
const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResultC);
|
|
const bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
|
|
|
|
return bOk;
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Handle a LLDB SBBreakpoint added event.
|
|
// Add more breakpoint information or overwrite existing information.
|
|
// Normally a break point session info objects exists by now when an MI command
|
|
// was issued to insert a break so the retrieval would normally always succeed
|
|
// however should a user type "b main" into a console then LLDB will create a
|
|
// breakpoint directly, hence no MI command, hence no previous record of the
|
|
// breakpoint so RecordBrkPtInfoGet() will fail. We still get the event though
|
|
// so need to create a breakpoint info object here and send appropriate MI
|
|
// response.
|
|
// Type: Method.
|
|
// Args: vEvent - (R) An LLDB broadcast event.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::HandleEventSBBreakpointAdded(const lldb::SBEvent &vEvent)
|
|
{
|
|
lldb::SBBreakpoint brkPt = lldb::SBBreakpoint::GetBreakpointFromEvent(vEvent);
|
|
if (!brkPt.IsValid())
|
|
return MIstatus::success;
|
|
|
|
CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
|
|
CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfo;
|
|
if (!rSessionInfo.GetBrkPtInfo(brkPt, sBrkPtInfo))
|
|
{
|
|
SetErrorDescription(
|
|
CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_GET), "HandleEventSBBreakpointAdded()", brkPt.GetID()));
|
|
return MIstatus::failure;
|
|
}
|
|
|
|
// CODETAG_LLDB_BREAKPOINT_CREATION
|
|
// This is in a worker thread
|
|
CMICmnLLDBDebugSessionInfo::SBrkPtInfo sBrkPtInfoRec;
|
|
const bool bBrkPtExistAlready = rSessionInfo.RecordBrkPtInfoGet(brkPt.GetID(), sBrkPtInfoRec);
|
|
if (bBrkPtExistAlready)
|
|
{
|
|
// Update breakpoint information object
|
|
sBrkPtInfo.m_bDisp = sBrkPtInfoRec.m_bDisp;
|
|
sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
|
|
sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
|
|
sBrkPtInfo.m_strOptThrdGrp.clear();
|
|
sBrkPtInfo.m_nTimes = brkPt.GetHitCount();
|
|
sBrkPtInfo.m_strOrigLoc = sBrkPtInfoRec.m_strOrigLoc;
|
|
sBrkPtInfo.m_nIgnore = sBrkPtInfoRec.m_nIgnore;
|
|
sBrkPtInfo.m_bPending = sBrkPtInfoRec.m_bPending;
|
|
sBrkPtInfo.m_bCondition = sBrkPtInfoRec.m_bCondition;
|
|
sBrkPtInfo.m_strCondition = sBrkPtInfoRec.m_strCondition;
|
|
sBrkPtInfo.m_bBrkPtThreadId = sBrkPtInfoRec.m_bBrkPtThreadId;
|
|
sBrkPtInfo.m_nBrkPtThreadId = sBrkPtInfoRec.m_nBrkPtThreadId;
|
|
}
|
|
else
|
|
{
|
|
// Create a breakpoint information object
|
|
sBrkPtInfo.m_bDisp = brkPt.IsOneShot();
|
|
sBrkPtInfo.m_bEnabled = brkPt.IsEnabled();
|
|
sBrkPtInfo.m_bHaveArgOptionThreadGrp = false;
|
|
sBrkPtInfo.m_strOptThrdGrp.clear();
|
|
sBrkPtInfo.m_strOrigLoc = CMIUtilString::Format("%s:%d", sBrkPtInfo.m_fileName.c_str(), sBrkPtInfo.m_nLine);
|
|
sBrkPtInfo.m_nIgnore = brkPt.GetIgnoreCount();
|
|
sBrkPtInfo.m_bPending = false;
|
|
const MIchar *pStrCondition = brkPt.GetCondition();
|
|
sBrkPtInfo.m_bCondition = (pStrCondition != nullptr) ? true : false;
|
|
sBrkPtInfo.m_strCondition = (pStrCondition != nullptr) ? pStrCondition : "??";
|
|
sBrkPtInfo.m_bBrkPtThreadId = (brkPt.GetThreadID() != 0) ? true : false;
|
|
sBrkPtInfo.m_nBrkPtThreadId = brkPt.GetThreadID();
|
|
}
|
|
|
|
CMICmnMIValueTuple miValueTuple;
|
|
if (!rSessionInfo.MIResponseFormBrkPtInfo(sBrkPtInfo, miValueTuple))
|
|
{
|
|
SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE), "HandleEventSBBreakpointAdded()"));
|
|
return MIstatus::failure;
|
|
}
|
|
|
|
bool bOk = MIstatus::success;
|
|
if (bBrkPtExistAlready)
|
|
{
|
|
// 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\"}"
|
|
const CMICmnMIValueResult miValueResult("bkpt", miValueTuple);
|
|
const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointModified, miValueResult);
|
|
bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
|
|
}
|
|
else
|
|
{
|
|
// CODETAG_LLDB_BRKPT_ID_MAX
|
|
if (brkPt.GetID() > (lldb::break_id_t)rSessionInfo.m_nBrkPointCntMax)
|
|
{
|
|
SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_CMD_ERR_BRKPT_CNT_EXCEEDED), "HandleEventSBBreakpointAdded()",
|
|
rSessionInfo.m_nBrkPointCntMax, sBrkPtInfo.m_id));
|
|
return MIstatus::failure;
|
|
}
|
|
if (!rSessionInfo.RecordBrkPtInfo(brkPt.GetID(), sBrkPtInfo))
|
|
{
|
|
SetErrorDescription(
|
|
CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_BRKPT_INFO_SET), "HandleEventSBBreakpointAdded()", sBrkPtInfo.m_id));
|
|
return MIstatus::failure;
|
|
}
|
|
|
|
// MI print
|
|
// "=breakpoint-created,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\"}"
|
|
const CMICmnMIValueResult miValueResult("bkpt", miValueTuple);
|
|
const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_BreakPointCreated, miValueResult);
|
|
bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
|
|
}
|
|
|
|
return bOk;
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Handle a LLDB SBThread event.
|
|
// Type: Method.
|
|
// Args: vEvent - (R) An LLDB broadcast event.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::HandleEventSBThread(const lldb::SBEvent &vEvent)
|
|
{
|
|
if (!ChkForStateChanges())
|
|
return MIstatus::failure;
|
|
|
|
bool bOk = MIstatus::success;
|
|
const MIchar *pEventType = "";
|
|
const MIuint nEventType = vEvent.GetType();
|
|
switch (nEventType)
|
|
{
|
|
case lldb::SBThread::eBroadcastBitStackChanged:
|
|
pEventType = "eBroadcastBitStackChanged";
|
|
bOk = HandleEventSBThreadBitStackChanged(vEvent);
|
|
break;
|
|
case lldb::SBThread::eBroadcastBitThreadSuspended:
|
|
pEventType = "eBroadcastBitThreadSuspended";
|
|
bOk = HandleEventSBThreadSuspended(vEvent);
|
|
break;
|
|
case lldb::SBThread::eBroadcastBitThreadResumed:
|
|
pEventType = "eBroadcastBitThreadResumed";
|
|
break;
|
|
case lldb::SBThread::eBroadcastBitSelectedFrameChanged:
|
|
pEventType = "eBroadcastBitSelectedFrameChanged";
|
|
break;
|
|
case lldb::SBThread::eBroadcastBitThreadSelected:
|
|
pEventType = "eBroadcastBitThreadSelected";
|
|
break;
|
|
default:
|
|
{
|
|
const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBThread", (MIuint)nEventType));
|
|
SetErrorDescription(msg);
|
|
return MIstatus::failure;
|
|
}
|
|
}
|
|
m_pLog->WriteLog(CMIUtilString::Format("##### An SBThread event occurred: %s", pEventType));
|
|
|
|
return bOk;
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Handle a LLDB SBThread event.
|
|
// Type: Method.
|
|
// Args: vEvent - (R) An LLDB broadcast event.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadSuspended(const lldb::SBEvent &vEvent)
|
|
{
|
|
lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent(vEvent);
|
|
if (!thread.IsValid())
|
|
return MIstatus::success;
|
|
|
|
const lldb::StopReason eStopReason = thread.GetStopReason();
|
|
if (eStopReason != lldb::eStopReasonSignal)
|
|
return MIstatus::success;
|
|
|
|
// MI print "@thread=%d,signal=%lld"
|
|
const MIuint64 nId = thread.GetStopReasonDataAtIndex(0);
|
|
const CMIUtilString strThread(CMIUtilString::Format("%d", thread.GetThreadID()));
|
|
const CMICmnMIValueConst miValueConst(strThread);
|
|
const CMICmnMIValueResult miValueResult("thread", miValueConst);
|
|
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Thread, miValueResult);
|
|
const CMIUtilString strSignal(CMIUtilString::Format("%lld", nId));
|
|
const CMICmnMIValueConst miValueConst2(strSignal);
|
|
const CMICmnMIValueResult miValueResult2("signal", miValueConst2);
|
|
bool bOk = miOutOfBandRecord.Add(miValueResult2);
|
|
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
|
|
|
|
return bOk;
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Handle a LLDB SBThread event.
|
|
// Type: Method.
|
|
// Args: vEvent - (R) An LLDB broadcast event.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadBitStackChanged(const lldb::SBEvent &vEvent)
|
|
{
|
|
lldb::SBThread thread = lldb::SBThread::GetThreadFromEvent(vEvent);
|
|
if (!thread.IsValid())
|
|
return MIstatus::success;
|
|
|
|
lldb::SBStream streamOut;
|
|
const bool bOk = thread.GetStatus(streamOut);
|
|
return bOk && TextToStdout(streamOut.GetData());
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Handle a LLDB SBCommandInterpreter event.
|
|
// Type: Method.
|
|
// Args: vEvent - (R) An LLDB command interpreter event.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::HandleEventSBCommandInterpreter(const lldb::SBEvent &vEvent)
|
|
{
|
|
// This function is not used
|
|
// *** This function is under development
|
|
|
|
const MIchar *pEventType = "";
|
|
const MIuint nEventType = vEvent.GetType();
|
|
switch (nEventType)
|
|
{
|
|
case lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit:
|
|
pEventType = "eBroadcastBitThreadShouldExit";
|
|
// ToDo: IOR: Reminder to maybe handle this here
|
|
// const MIuint nEventType = event.GetType();
|
|
// if (nEventType & lldb::SBCommandInterpreter::eBroadcastBitThreadShouldExit)
|
|
//{
|
|
// m_pClientDriver->SetExitApplicationFlag();
|
|
// vrbYesExit = true;
|
|
// return MIstatus::success;
|
|
//} break;
|
|
case lldb::SBCommandInterpreter::eBroadcastBitResetPrompt:
|
|
pEventType = "eBroadcastBitResetPrompt";
|
|
break;
|
|
case lldb::SBCommandInterpreter::eBroadcastBitQuitCommandReceived:
|
|
pEventType = "eBroadcastBitQuitCommandReceived";
|
|
break;
|
|
case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousOutputData:
|
|
pEventType = "eBroadcastBitAsynchronousOutputData";
|
|
break;
|
|
case lldb::SBCommandInterpreter::eBroadcastBitAsynchronousErrorData:
|
|
pEventType = "eBroadcastBitAsynchronousErrorData";
|
|
break;
|
|
default:
|
|
{
|
|
const CMIUtilString msg(
|
|
CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBCommandInterpreter", (MIuint)nEventType));
|
|
SetErrorDescription(msg);
|
|
return MIstatus::failure;
|
|
}
|
|
}
|
|
m_pLog->WriteLog(CMIUtilString::Format("##### An SBCommandInterpreter event occurred: %s", pEventType));
|
|
|
|
return MIstatus::success;
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Handle SBProcess event eBroadcastBitStateChanged.
|
|
// Type: Method.
|
|
// Args: vEvent - (R) An LLDB event object.
|
|
// vrbExitAppEvent - (W) True - Received LLDB exit app event, false = did not.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::HandleProcessEventBroadcastBitStateChanged(const lldb::SBEvent &vEvent, bool &vrbExitAppEvent)
|
|
{
|
|
bool bOk = ChkForStateChanges();
|
|
bOk = bOk && GetProcessStdout();
|
|
bOk = bOk && GetProcessStderr();
|
|
if (!bOk)
|
|
return MIstatus::failure;
|
|
|
|
// Something changed in the process; get the event and report the process's current
|
|
// status and location
|
|
const lldb::StateType eEventState = lldb::SBProcess::GetStateFromEvent(vEvent);
|
|
if (eEventState == lldb::eStateInvalid)
|
|
return MIstatus::success;
|
|
|
|
lldb::SBProcess process = lldb::SBProcess::GetProcessFromEvent(vEvent);
|
|
if (!process.IsValid())
|
|
{
|
|
const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_PROCESS_INVALID), "SBProcess",
|
|
"HandleProcessEventBroadcastBitStateChanged()"));
|
|
SetErrorDescription(msg);
|
|
return MIstatus::failure;
|
|
}
|
|
|
|
bool bShouldBrk = true;
|
|
const MIchar *pEventType = "";
|
|
switch (eEventState)
|
|
{
|
|
case lldb::eStateUnloaded:
|
|
pEventType = "eStateUnloaded";
|
|
break;
|
|
case lldb::eStateConnected:
|
|
pEventType = "eStateConnected";
|
|
break;
|
|
case lldb::eStateAttaching:
|
|
pEventType = "eStateAttaching";
|
|
break;
|
|
case lldb::eStateLaunching:
|
|
pEventType = "eStateLaunching";
|
|
break;
|
|
case lldb::eStateStopped:
|
|
pEventType = "eStateStopped";
|
|
bOk = HandleProcessEventStateStopped(bShouldBrk);
|
|
if (bShouldBrk)
|
|
break;
|
|
case lldb::eStateCrashed:
|
|
case lldb::eStateSuspended:
|
|
pEventType = "eStateSuspended";
|
|
bOk = HandleProcessEventStateSuspended(vEvent);
|
|
break;
|
|
case lldb::eStateRunning:
|
|
pEventType = "eStateRunning";
|
|
bOk = HandleProcessEventStateRunning();
|
|
break;
|
|
case lldb::eStateStepping:
|
|
pEventType = "eStateStepping";
|
|
break;
|
|
case lldb::eStateDetached:
|
|
pEventType = "eStateDetached";
|
|
break;
|
|
case lldb::eStateExited:
|
|
pEventType = "eStateExited";
|
|
vrbExitAppEvent = true;
|
|
bOk = HandleProcessEventStateExited();
|
|
break;
|
|
default:
|
|
{
|
|
const CMIUtilString msg(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT), "SBProcess BroadcastBitStateChanged",
|
|
(MIuint)eEventState));
|
|
SetErrorDescription(msg);
|
|
return MIstatus::failure;
|
|
}
|
|
}
|
|
|
|
// ToDo: Remove when finished coding application
|
|
m_pLog->WriteLog(CMIUtilString::Format("##### An SB Process event BroadcastBitStateChanged occurred: %s", pEventType));
|
|
|
|
return bOk;
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Asynchronous event handler for LLDB Process state suspended.
|
|
// Type: Method.
|
|
// Args: vEvent - (R) An LLDB event object.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateSuspended(const lldb::SBEvent &vEvent)
|
|
{
|
|
// Make sure the program hasn't been auto-restarted:
|
|
if (lldb::SBProcess::GetRestartedFromEvent(vEvent))
|
|
return MIstatus::success;
|
|
|
|
bool bOk = MIstatus::success;
|
|
lldb::SBDebugger &rDebugger = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger;
|
|
lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
|
|
lldb::SBTarget target = rProcess.GetTarget();
|
|
if (rDebugger.GetSelectedTarget() == target)
|
|
{
|
|
if (!UpdateSelectedThread())
|
|
return MIstatus::failure;
|
|
|
|
lldb::SBCommandReturnObject result;
|
|
const lldb::ReturnStatus status = rDebugger.GetCommandInterpreter().HandleCommand("process status", result, false);
|
|
MIunused(status);
|
|
bOk = TextToStderr(result.GetError());
|
|
bOk = bOk && TextToStdout(result.GetOutput());
|
|
}
|
|
else
|
|
{
|
|
lldb::SBStream streamOut;
|
|
const MIuint nTargetIndex = rDebugger.GetIndexOfTarget(target);
|
|
if (nTargetIndex != UINT_MAX)
|
|
streamOut.Printf("Target %d: (", nTargetIndex);
|
|
else
|
|
streamOut.Printf("Target <unknown index>: (");
|
|
target.GetDescription(streamOut, lldb::eDescriptionLevelBrief);
|
|
streamOut.Printf(") stopped.\n");
|
|
bOk = TextToStdout(streamOut.GetData());
|
|
}
|
|
|
|
return bOk;
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Print to stdout MI formatted text to indicate process stopped.
|
|
// Type: Method.
|
|
// Args: vwrbShouldBrk - (W) True = Yes break, false = do not.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateStopped(bool &vwrbShouldBrk)
|
|
{
|
|
if (!UpdateSelectedThread())
|
|
return MIstatus::failure;
|
|
|
|
const MIchar *pEventType = "";
|
|
bool bOk = MIstatus::success;
|
|
lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
|
|
const lldb::StopReason eStoppedReason = rProcess.GetSelectedThread().GetStopReason();
|
|
switch (eStoppedReason)
|
|
{
|
|
case lldb::eStopReasonInvalid:
|
|
pEventType = "eStopReasonInvalid";
|
|
vwrbShouldBrk = false;
|
|
break;
|
|
case lldb::eStopReasonNone:
|
|
pEventType = "eStopReasonNone";
|
|
break;
|
|
case lldb::eStopReasonTrace:
|
|
pEventType = "eStopReasonTrace";
|
|
bOk = HandleProcessEventStopReasonTrace();
|
|
break;
|
|
case lldb::eStopReasonBreakpoint:
|
|
pEventType = "eStopReasonBreakpoint";
|
|
bOk = HandleProcessEventStopReasonBreakpoint();
|
|
break;
|
|
case lldb::eStopReasonWatchpoint:
|
|
pEventType = "eStopReasonWatchpoint";
|
|
break;
|
|
case lldb::eStopReasonSignal:
|
|
pEventType = "eStopReasonSignal";
|
|
bOk = HandleProcessEventStopSignal(vwrbShouldBrk);
|
|
break;
|
|
case lldb::eStopReasonException:
|
|
pEventType = "eStopReasonException";
|
|
break;
|
|
case lldb::eStopReasonExec:
|
|
pEventType = "eStopReasonExec";
|
|
break;
|
|
case lldb::eStopReasonPlanComplete:
|
|
pEventType = "eStopReasonPlanComplete";
|
|
bOk = HandleProcessEventStopReasonTrace();
|
|
break;
|
|
case lldb::eStopReasonThreadExiting:
|
|
pEventType = "eStopReasonThreadExiting";
|
|
break;
|
|
case lldb::eStopReasonInstrumentation:
|
|
pEventType = "eStopReasonInstrumentation";
|
|
break;
|
|
}
|
|
|
|
// ToDo: Remove when finished coding application
|
|
m_pLog->WriteLog(CMIUtilString::Format("##### An SB Process event stop state occurred: %s", pEventType));
|
|
|
|
return bOk;
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Asynchronous event handler for LLDB Process stop signal.
|
|
// Type: Method.
|
|
// Args: vwrbShouldBrk - (W) True = Yes break, false = do not.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopSignal(bool &vwrbShouldBrk)
|
|
{
|
|
bool bOk = MIstatus::success;
|
|
|
|
lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
|
|
const MIuint64 nStopReason = rProcess.GetSelectedThread().GetStopReasonDataAtIndex(0);
|
|
switch (nStopReason)
|
|
{
|
|
case 2: // Terminal interrupt signal. SIGINT
|
|
{
|
|
// MI print "*stopped,reason=\"signal-received\",signal-name=\"SIGNINT\",signal-meaning=\"Interrupt\",frame={%s}"
|
|
const CMICmnMIValueConst miValueConst("signal-received");
|
|
const CMICmnMIValueResult miValueResult("reason", miValueConst);
|
|
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
|
|
const CMICmnMIValueConst miValueConst2("SIGINT");
|
|
const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2);
|
|
bOk = miOutOfBandRecord.Add(miValueResult2);
|
|
const CMICmnMIValueConst miValueConst3("Interrupt");
|
|
const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3);
|
|
bOk = bOk && miOutOfBandRecord.Add(miValueResult3);
|
|
CMICmnMIValueTuple miValueTuple;
|
|
bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple);
|
|
const CMICmnMIValueResult miValueResult5("frame", miValueTuple);
|
|
bOk = bOk && miOutOfBandRecord.Add(miValueResult5);
|
|
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
|
|
bOk = bOk && TextToStdout("(gdb)");
|
|
}
|
|
break;
|
|
case 11: // Invalid memory reference. SIGSEGV
|
|
{
|
|
// MI print "*stopped,reason=\"signal-received\",signal-name=\"SIGSEGV\",signal-meaning=\"Segmentation
|
|
// fault\",thread-id=\"%d\",frame={%s}"
|
|
const CMICmnMIValueConst miValueConst("signal-received");
|
|
const CMICmnMIValueResult miValueResult("reason", miValueConst);
|
|
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
|
|
const CMICmnMIValueConst miValueConst2("SIGSEGV");
|
|
const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2);
|
|
bOk = miOutOfBandRecord.Add(miValueResult2);
|
|
const CMICmnMIValueConst miValueConst3("Segmentation fault");
|
|
const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3);
|
|
bOk = bOk && miOutOfBandRecord.Add(miValueResult3);
|
|
const CMIUtilString strThreadId(CMIUtilString::Format("%d", rProcess.GetSelectedThread().GetIndexID()));
|
|
const CMICmnMIValueConst miValueConst4(strThreadId);
|
|
const CMICmnMIValueResult miValueResult4("thread-id", miValueConst4);
|
|
bOk = bOk && miOutOfBandRecord.Add(miValueResult4);
|
|
CMICmnMIValueTuple miValueTuple;
|
|
bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple);
|
|
const CMICmnMIValueResult miValueResult5("frame", miValueTuple);
|
|
bOk = bOk && miOutOfBandRecord.Add(miValueResult5);
|
|
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
|
|
// Note no "(gdb)" output here
|
|
}
|
|
break;
|
|
case 19:
|
|
if (rProcess.IsValid())
|
|
rProcess.Continue();
|
|
break;
|
|
case 5: // Trace/breakpoint trap. SIGTRAP
|
|
{
|
|
lldb::SBThread thread = rProcess.GetSelectedThread();
|
|
const MIuint nFrames = thread.GetNumFrames();
|
|
if (nFrames > 0)
|
|
{
|
|
lldb::SBFrame frame = thread.GetFrameAtIndex(0);
|
|
const char *pFnName = frame.GetFunctionName();
|
|
if (pFnName != nullptr)
|
|
{
|
|
const CMIUtilString fnName = CMIUtilString(pFnName);
|
|
static const CMIUtilString threadCloneFn = CMIUtilString("__pthread_clone");
|
|
|
|
if (CMIUtilString::Compare(threadCloneFn, fnName))
|
|
{
|
|
if (rProcess.IsValid())
|
|
{
|
|
rProcess.Continue();
|
|
vwrbShouldBrk = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
default:
|
|
{
|
|
// MI print "*stopped,reason=\"signal-received\",signal=\"%lld\",stopped-threads=\"all\""
|
|
const CMICmnMIValueConst miValueConst("signal-received");
|
|
const CMICmnMIValueResult miValueResult("reason", miValueConst);
|
|
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
|
|
const CMIUtilString strReason(CMIUtilString::Format("%lld", nStopReason));
|
|
const CMICmnMIValueConst miValueConst2(strReason);
|
|
const CMICmnMIValueResult miValueResult2("signal", miValueConst2);
|
|
bOk = miOutOfBandRecord.Add(miValueResult2);
|
|
const CMICmnMIValueConst miValueConst3("all");
|
|
const CMICmnMIValueResult miValueResult3("stopped-threads", miValueConst3);
|
|
bOk = bOk && miOutOfBandRecord.Add(miValueResult3);
|
|
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
|
|
bOk = bOk && TextToStdout("(gdb)");
|
|
}
|
|
} // switch( nStopReason )
|
|
|
|
return bOk;
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Form partial MI response in a MI value tuple object.
|
|
// Type: Method.
|
|
// Args: vwrMiValueTuple - (W) MI value tuple object.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::MiHelpGetCurrentThreadFrame(CMICmnMIValueTuple &vwrMiValueTuple)
|
|
{
|
|
CMIUtilString strThreadFrame;
|
|
lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
|
|
lldb::SBThread thread = rProcess.GetSelectedThread();
|
|
const MIuint nFrame = thread.GetNumFrames();
|
|
if (nFrame == 0)
|
|
{
|
|
// MI print "addr=\"??\",func=\"??\",file=\"??\",fullname=\"??\",line=\"??\""
|
|
const CMICmnMIValueConst miValueConst("??");
|
|
const CMICmnMIValueResult miValueResult("addr", miValueConst);
|
|
CMICmnMIValueTuple miValueTuple(miValueResult);
|
|
const CMICmnMIValueResult miValueResult2("func", miValueConst);
|
|
miValueTuple.Add(miValueResult2);
|
|
const CMICmnMIValueResult miValueResult4("file", miValueConst);
|
|
miValueTuple.Add(miValueResult4);
|
|
const CMICmnMIValueResult miValueResult5("fullname", miValueConst);
|
|
miValueTuple.Add(miValueResult5);
|
|
const CMICmnMIValueResult miValueResult6("line", miValueConst);
|
|
miValueTuple.Add(miValueResult6);
|
|
|
|
vwrMiValueTuple = miValueTuple;
|
|
|
|
return MIstatus::success;
|
|
}
|
|
|
|
CMICmnMIValueTuple miValueTuple;
|
|
if (!CMICmnLLDBDebugSessionInfo::Instance().MIResponseFormFrameInfo(thread, 0, miValueTuple))
|
|
{
|
|
SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FORM_MI_RESPONSE), "MiHelpGetCurrentThreadFrame()"));
|
|
return MIstatus::failure;
|
|
}
|
|
|
|
vwrMiValueTuple = miValueTuple;
|
|
|
|
return MIstatus::success;
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Asynchronous event handler for LLDB Process stop reason breakpoint.
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonBreakpoint(void)
|
|
{
|
|
// CODETAG_DEBUG_SESSION_RUNNING_PROG_RECEIVED_SIGINT_PAUSE_PROGRAM
|
|
if (!CMIDriver::Instance().SetDriverStateRunningNotDebugging())
|
|
{
|
|
const CMIUtilString &rErrMsg(CMIDriver::Instance().GetErrorDescription());
|
|
SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_SETNEWDRIVERSTATE),
|
|
"HandleProcessEventStopReasonBreakpoint()", rErrMsg.c_str()));
|
|
return MIstatus::failure;
|
|
}
|
|
|
|
lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
|
|
const MIuint64 brkPtId = rProcess.GetSelectedThread().GetStopReasonDataAtIndex(0);
|
|
lldb::SBBreakpoint brkPt = CMICmnLLDBDebugSessionInfo::Instance().m_lldbTarget.GetBreakpointAtIndex((MIuint)brkPtId);
|
|
|
|
return MiStoppedAtBreakPoint(brkPtId, brkPt);
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Form the MI Out-of-band response for stopped reason on hitting a break point.
|
|
// Type: Method.
|
|
// Args: vBrkPtId - (R) The LLDB break point's ID
|
|
// vBrkPt - (R) THe LLDB break point object.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::MiStoppedAtBreakPoint(const MIuint64 vBrkPtId, const lldb::SBBreakpoint &vBrkPt)
|
|
{
|
|
bool bOk = MIstatus::success;
|
|
|
|
lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
|
|
lldb::SBThread thread = rProcess.GetSelectedThread();
|
|
const MIuint nFrame = thread.GetNumFrames();
|
|
if (nFrame == 0)
|
|
{
|
|
// MI print "*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"%d\",frame={},thread-id=\"%d\",stopped-threads=\"all\""
|
|
const CMICmnMIValueConst miValueConst("breakpoint-hit");
|
|
const CMICmnMIValueResult miValueResult("reason", miValueConst);
|
|
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
|
|
const CMICmnMIValueConst miValueConst2("del");
|
|
const CMICmnMIValueResult miValueResult2("disp", miValueConst2);
|
|
bOk = miOutOfBandRecord.Add(miValueResult2);
|
|
const CMIUtilString strBkp(CMIUtilString::Format("%d", vBrkPtId));
|
|
const CMICmnMIValueConst miValueConst3(strBkp);
|
|
CMICmnMIValueResult miValueResult3("bkptno", miValueConst3);
|
|
bOk = bOk && miOutOfBandRecord.Add(miValueResult3);
|
|
const CMICmnMIValueConst miValueConst4("{}");
|
|
const CMICmnMIValueResult miValueResult4("frame", miValueConst4);
|
|
bOk = bOk && miOutOfBandRecord.Add(miValueResult4);
|
|
const CMIUtilString strThreadId(CMIUtilString::Format("%d", vBrkPt.GetThreadIndex()));
|
|
const CMICmnMIValueConst miValueConst5(strThreadId);
|
|
const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5);
|
|
bOk = bOk && miOutOfBandRecord.Add(miValueResult5);
|
|
const CMICmnMIValueConst miValueConst6("all");
|
|
const CMICmnMIValueResult miValueResult6("stopped-threads", miValueConst6);
|
|
bOk = bOk && miOutOfBandRecord.Add(miValueResult6);
|
|
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
|
|
bOk = bOk && TextToStdout("(gdb)");
|
|
return bOk;
|
|
}
|
|
|
|
CMICmnLLDBDebugSessionInfo &rSession = CMICmnLLDBDebugSessionInfo::Instance();
|
|
|
|
lldb::SBFrame frame = thread.GetFrameAtIndex(0);
|
|
lldb::addr_t pc = 0;
|
|
CMIUtilString fnName;
|
|
CMIUtilString fileName;
|
|
CMIUtilString path;
|
|
MIuint nLine = 0;
|
|
if (!rSession.GetFrameInfo(frame, pc, fnName, fileName, path, nLine))
|
|
{
|
|
SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET), "MiStoppedAtBreakPoint()"));
|
|
return MIstatus::failure;
|
|
}
|
|
|
|
// MI print
|
|
// "*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"%d\",frame={addr=\"0x%08x\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"},thread-id=\"%d\",stopped-threads=\"all\""
|
|
const CMICmnMIValueConst miValueConst("breakpoint-hit");
|
|
const CMICmnMIValueResult miValueResult("reason", miValueConst);
|
|
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
|
|
const CMICmnMIValueConst miValueConstA("del");
|
|
const CMICmnMIValueResult miValueResultA("disp", miValueConstA);
|
|
bOk = miOutOfBandRecord.Add(miValueResultA);
|
|
const CMIUtilString strBkp(CMIUtilString::Format("%d", vBrkPtId));
|
|
const CMICmnMIValueConst miValueConstB(strBkp);
|
|
CMICmnMIValueResult miValueResultB("bkptno", miValueConstB);
|
|
bOk = bOk && miOutOfBandRecord.Add(miValueResultB);
|
|
|
|
// frame={addr=\"0x%08x\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"}
|
|
if (bOk)
|
|
{
|
|
CMICmnMIValueList miValueList(true);
|
|
const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Arguments;
|
|
bOk = rSession.MIResponseFormVariableInfo2(frame, maskVarTypes, miValueList);
|
|
|
|
CMICmnMIValueTuple miValueTuple;
|
|
bOk = bOk && rSession.MIResponseFormFrameInfo2(pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple);
|
|
const CMICmnMIValueResult miValueResult8("frame", miValueTuple);
|
|
bOk = bOk && miOutOfBandRecord.Add(miValueResult8);
|
|
}
|
|
|
|
// Add to MI thread-id=\"%d\",stopped-threads=\"all\"
|
|
if (bOk)
|
|
{
|
|
const CMIUtilString strThreadId(CMIUtilString::Format("%d", thread.GetIndexID()));
|
|
const CMICmnMIValueConst miValueConst8(strThreadId);
|
|
const CMICmnMIValueResult miValueResult8("thread-id", miValueConst8);
|
|
bOk = miOutOfBandRecord.Add(miValueResult8);
|
|
}
|
|
if (bOk)
|
|
{
|
|
const CMICmnMIValueConst miValueConst9("all");
|
|
const CMICmnMIValueResult miValueResult9("stopped-threads", miValueConst9);
|
|
bOk = miOutOfBandRecord.Add(miValueResult9);
|
|
bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
|
|
bOk = bOk && TextToStdout("(gdb)");
|
|
}
|
|
|
|
return MIstatus::success;
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Asynchronous event handler for LLDB Process stop reason trace.
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopReasonTrace(void)
|
|
{
|
|
bool bOk = true;
|
|
lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
|
|
lldb::SBThread thread = rProcess.GetSelectedThread();
|
|
const MIuint nFrame = thread.GetNumFrames();
|
|
if (nFrame == 0)
|
|
{
|
|
// MI print "*stopped,reason=\"trace\",stopped-threads=\"all\""
|
|
const CMICmnMIValueConst miValueConst("trace");
|
|
const CMICmnMIValueResult miValueResult("reason", miValueConst);
|
|
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
|
|
const CMICmnMIValueConst miValueConst2("all");
|
|
const CMICmnMIValueResult miValueResult2("stopped-threads", miValueConst2);
|
|
bOk = miOutOfBandRecord.Add(miValueResult2);
|
|
bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
|
|
bOk = bOk && TextToStdout("(gdb)");
|
|
return bOk;
|
|
}
|
|
|
|
CMICmnLLDBDebugSessionInfo &rSession = CMICmnLLDBDebugSessionInfo::Instance();
|
|
|
|
// MI print
|
|
// "*stopped,reason=\"end-stepping-range\",frame={addr=\"0x%08x\",func=\"%s\",args=[\"%s\"],file=\"%s\",fullname=\"%s\",line=\"%d\"},thread-id=\"%d\",stopped-threads=\"all\""
|
|
lldb::SBFrame frame = thread.GetFrameAtIndex(0);
|
|
lldb::addr_t pc = 0;
|
|
CMIUtilString fnName;
|
|
CMIUtilString fileName;
|
|
CMIUtilString path;
|
|
MIuint nLine = 0;
|
|
if (!rSession.GetFrameInfo(frame, pc, fnName, fileName, path, nLine))
|
|
{
|
|
SetErrorDescription(CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_FRAME_INFO_GET), "HandleProcessEventStopReasonTrace()"));
|
|
return MIstatus::failure;
|
|
}
|
|
|
|
// Function args
|
|
CMICmnMIValueList miValueList(true);
|
|
const MIuint maskVarTypes = CMICmnLLDBDebugSessionInfo::eVariableType_Arguments;
|
|
if (!rSession.MIResponseFormVariableInfo2(frame, maskVarTypes, miValueList))
|
|
return MIstatus::failure;
|
|
CMICmnMIValueTuple miValueTuple;
|
|
if (!rSession.MIResponseFormFrameInfo2(pc, miValueList.GetString(), fnName, fileName, path, nLine, miValueTuple))
|
|
return MIstatus::failure;
|
|
|
|
const CMICmnMIValueConst miValueConst("end-stepping-range");
|
|
const CMICmnMIValueResult miValueResult("reason", miValueConst);
|
|
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
|
|
const CMICmnMIValueResult miValueResult2("frame", miValueTuple);
|
|
bOk = miOutOfBandRecord.Add(miValueResult2);
|
|
|
|
// Add to MI thread-id=\"%d\",stopped-threads=\"all\"
|
|
if (bOk)
|
|
{
|
|
const CMIUtilString strThreadId(CMIUtilString::Format("%d", thread.GetIndexID()));
|
|
const CMICmnMIValueConst miValueConst8(strThreadId);
|
|
const CMICmnMIValueResult miValueResult8("thread-id", miValueConst8);
|
|
bOk = miOutOfBandRecord.Add(miValueResult8);
|
|
}
|
|
if (bOk)
|
|
{
|
|
const CMICmnMIValueConst miValueConst9("all");
|
|
const CMICmnMIValueResult miValueResult9("stopped-threads", miValueConst9);
|
|
bOk = miOutOfBandRecord.Add(miValueResult9);
|
|
bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
|
|
bOk = bOk && TextToStdout("(gdb)");
|
|
}
|
|
|
|
return bOk;
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Asynchronous function update selected thread.
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::UpdateSelectedThread(void)
|
|
{
|
|
lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess();
|
|
if (!process.IsValid())
|
|
return MIstatus::success;
|
|
|
|
lldb::SBThread currentThread = process.GetSelectedThread();
|
|
lldb::SBThread thread;
|
|
const lldb::StopReason eCurrentThreadStoppedReason = currentThread.GetStopReason();
|
|
if (!currentThread.IsValid() || (eCurrentThreadStoppedReason == lldb::eStopReasonInvalid) ||
|
|
(eCurrentThreadStoppedReason == lldb::eStopReasonNone))
|
|
{
|
|
// Prefer a thread that has just completed its plan over another thread as current thread
|
|
lldb::SBThread planThread;
|
|
lldb::SBThread otherThread;
|
|
const size_t nThread = process.GetNumThreads();
|
|
for (MIuint i = 0; i < nThread; i++)
|
|
{
|
|
// GetThreadAtIndex() uses a base 0 index
|
|
// GetThreadByIndexID() uses a base 1 index
|
|
thread = process.GetThreadAtIndex(i);
|
|
const lldb::StopReason eThreadStopReason = thread.GetStopReason();
|
|
switch (eThreadStopReason)
|
|
{
|
|
case lldb::eStopReasonTrace:
|
|
case lldb::eStopReasonBreakpoint:
|
|
case lldb::eStopReasonWatchpoint:
|
|
case lldb::eStopReasonSignal:
|
|
case lldb::eStopReasonException:
|
|
if (!otherThread.IsValid())
|
|
otherThread = thread;
|
|
break;
|
|
case lldb::eStopReasonPlanComplete:
|
|
if (!planThread.IsValid())
|
|
planThread = thread;
|
|
break;
|
|
case lldb::eStopReasonInvalid:
|
|
case lldb::eStopReasonNone:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
if (planThread.IsValid())
|
|
process.SetSelectedThread(planThread);
|
|
else if (otherThread.IsValid())
|
|
process.SetSelectedThread(otherThread);
|
|
else
|
|
{
|
|
if (currentThread.IsValid())
|
|
thread = currentThread;
|
|
else
|
|
thread = process.GetThreadAtIndex(0);
|
|
|
|
if (thread.IsValid())
|
|
process.SetSelectedThread(thread);
|
|
}
|
|
} // if( !currentThread.IsValid() || (eCurrentThreadStoppedReason == lldb::eStopReasonInvalid) || (eCurrentThreadStoppedReason ==
|
|
// lldb::eStopReasonNone) )
|
|
|
|
return MIstatus::success;
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Print to stdout "*running,thread-id=\"all\"", "(gdb)".
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateRunning(void)
|
|
{
|
|
CMICmnMIValueConst miValueConst("all");
|
|
CMICmnMIValueResult miValueResult("thread-id", miValueConst);
|
|
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_Running, miValueResult);
|
|
bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
|
|
bOk = bOk && TextToStdout("(gdb)");
|
|
|
|
return bOk;
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Print to stdout "=thread-exited,id=\"%ld\",group-id=\"i1\"",
|
|
// "=thread-group-exited,id=\"i1\",exit-code=\"0\""),
|
|
// "*stopped,reason=\"exited-normally\"",
|
|
// "(gdb)"
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStateExited(void)
|
|
{
|
|
const CMIUtilString strId(CMIUtilString::Format("%ld", 1));
|
|
CMICmnMIValueConst miValueConst(strId);
|
|
CMICmnMIValueResult miValueResult("id", miValueConst);
|
|
CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult);
|
|
CMICmnMIValueConst miValueConst2("i1");
|
|
CMICmnMIValueResult miValueResult2("group-id", miValueConst2);
|
|
bool bOk = miOutOfBandRecord.Add(miValueResult2);
|
|
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
|
|
if (bOk)
|
|
{
|
|
CMICmnMIValueConst miValueConst3("i1");
|
|
CMICmnMIValueResult miValueResult3("id", miValueConst3);
|
|
CMICmnMIOutOfBandRecord miOutOfBandRecord2(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupExited, miValueResult3);
|
|
CMICmnMIValueConst miValueConst2("0");
|
|
CMICmnMIValueResult miValueResult2("exit-code", miValueConst2);
|
|
bOk = miOutOfBandRecord2.Add(miValueResult2);
|
|
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord2);
|
|
}
|
|
if (bOk)
|
|
{
|
|
CMICmnMIValueConst miValueConst4("exited-normally");
|
|
CMICmnMIValueResult miValueResult4("reason", miValueConst4);
|
|
CMICmnMIOutOfBandRecord miOutOfBandRecord3(CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult4);
|
|
bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord3);
|
|
}
|
|
bOk = bOk && TextToStdout("(gdb)");
|
|
|
|
return bOk;
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Drain all stdout so we don't see any output come after we print our prompts.
|
|
// The process has stuff waiting for stdout; get it and write it out to the
|
|
// appropriate place.
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::GetProcessStdout(void)
|
|
{
|
|
bool bOk = MIstatus::success;
|
|
|
|
char c;
|
|
size_t nBytes = 0;
|
|
CMIUtilString text;
|
|
lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess();
|
|
while (process.GetSTDOUT(&c, 1) > 0)
|
|
{
|
|
CMIUtilString str;
|
|
if (ConvertPrintfCtrlCodeToString(c, str))
|
|
text += str;
|
|
nBytes++;
|
|
}
|
|
if (nBytes > 0)
|
|
{
|
|
const CMIUtilString t(CMIUtilString::Format("~\"%s\"", text.c_str()));
|
|
bOk = TextToStdout(t);
|
|
}
|
|
|
|
return bOk;
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Drain all stderr so we don't see any output come after we print our prompts.
|
|
// The process has stuff waiting for stderr; get it and write it out to the
|
|
// appropriate place.
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::GetProcessStderr(void)
|
|
{
|
|
bool bOk = MIstatus::success;
|
|
|
|
char c;
|
|
size_t nBytes = 0;
|
|
CMIUtilString text;
|
|
lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance().m_rLldbDebugger.GetSelectedTarget().GetProcess();
|
|
while (process.GetSTDERR(&c, 1) > 0)
|
|
{
|
|
CMIUtilString str;
|
|
if (ConvertPrintfCtrlCodeToString(c, str))
|
|
text += str;
|
|
nBytes++;
|
|
}
|
|
if (nBytes > 0)
|
|
{
|
|
const CMIUtilString t(CMIUtilString::Format("~\"%s\"", text.c_str()));
|
|
bOk = TextToStdout(t);
|
|
}
|
|
|
|
return bOk;
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Convert text stream control codes to text equivalent.
|
|
// Type: Method.
|
|
// Args: vCtrl - (R) The control code.
|
|
// vwrStrEquivalent - (W) The text equivalent.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::ConvertPrintfCtrlCodeToString(const MIchar vCtrl, CMIUtilString &vwrStrEquivalent)
|
|
{
|
|
switch (vCtrl)
|
|
{
|
|
case '\033':
|
|
vwrStrEquivalent = "\\e";
|
|
break;
|
|
case '\a':
|
|
vwrStrEquivalent = "\\a";
|
|
break;
|
|
case '\b':
|
|
vwrStrEquivalent = "\\b";
|
|
break;
|
|
case '\f':
|
|
vwrStrEquivalent = "\\f";
|
|
break;
|
|
case '\n':
|
|
vwrStrEquivalent = "\\n";
|
|
break;
|
|
case '\r':
|
|
vwrStrEquivalent = "\\r";
|
|
break;
|
|
case '\t':
|
|
vwrStrEquivalent = "\\t";
|
|
break;
|
|
case '\v':
|
|
vwrStrEquivalent = "\\v";
|
|
break;
|
|
default:
|
|
vwrStrEquivalent = CMIUtilString::Format("%c", vCtrl);
|
|
break;
|
|
}
|
|
|
|
return MIstatus::success;
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Asynchronous event function check for state changes.
|
|
// Type: Method.
|
|
// Args: None.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::ChkForStateChanges(void)
|
|
{
|
|
lldb::SBProcess &rProcess = CMICmnLLDBDebugSessionInfo::Instance().m_lldbProcess;
|
|
if (!rProcess.IsValid())
|
|
return MIstatus::success;
|
|
lldb::SBTarget &rTarget = CMICmnLLDBDebugSessionInfo::Instance().m_lldbTarget;
|
|
if (!rTarget.IsValid())
|
|
return MIstatus::success;
|
|
|
|
bool bOk = MIstatus::success;
|
|
|
|
// Check for created threads
|
|
const MIuint nThread = rProcess.GetNumThreads();
|
|
for (MIuint i = 0; i < nThread; i++)
|
|
{
|
|
// GetThreadAtIndex() uses a base 0 index
|
|
// GetThreadByIndexID() uses a base 1 index
|
|
lldb::SBThread thread = rProcess.GetThreadAtIndex(i);
|
|
if (!thread.IsValid())
|
|
continue;
|
|
|
|
CMICmnLLDBDebugSessionInfo::VecActiveThreadId_t::const_iterator it =
|
|
CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.begin();
|
|
bool bFound = false;
|
|
while (it != CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.end())
|
|
{
|
|
const MIuint nThreadId = *it;
|
|
if (nThreadId == i)
|
|
{
|
|
bFound = true;
|
|
break;
|
|
}
|
|
|
|
// Next
|
|
++it;
|
|
}
|
|
if (!bFound)
|
|
{
|
|
CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.push_back(i);
|
|
|
|
// Form MI "=thread-created,id=\"%d\",group-id=\"i1\""
|
|
const CMIUtilString strValue(CMIUtilString::Format("%d", thread.GetIndexID()));
|
|
const CMICmnMIValueConst miValueConst(strValue);
|
|
const CMICmnMIValueResult miValueResult("id", miValueConst);
|
|
CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated, miValueResult);
|
|
const CMICmnMIValueConst miValueConst2("i1");
|
|
const CMICmnMIValueResult miValueResult2("group-id", miValueConst2);
|
|
bOk = miOutOfBand.Add(miValueResult2);
|
|
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBand);
|
|
if (!bOk)
|
|
return MIstatus::failure;
|
|
}
|
|
}
|
|
|
|
lldb::SBThread currentThread = rProcess.GetSelectedThread();
|
|
if (currentThread.IsValid())
|
|
{
|
|
const MIuint threadId = currentThread.GetIndexID();
|
|
if (CMICmnLLDBDebugSessionInfo::Instance().m_currentSelectedThread != threadId)
|
|
{
|
|
CMICmnLLDBDebugSessionInfo::Instance().m_currentSelectedThread = threadId;
|
|
|
|
// Form MI "=thread-selected,id=\"%d\""
|
|
const CMIUtilString strValue(CMIUtilString::Format("%d", currentThread.GetIndexID()));
|
|
const CMICmnMIValueConst miValueConst(strValue);
|
|
const CMICmnMIValueResult miValueResult("id", miValueConst);
|
|
CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected, miValueResult);
|
|
if (!MiOutOfBandRecordToStdout(miOutOfBand))
|
|
return MIstatus::failure;
|
|
}
|
|
}
|
|
|
|
// Check for invalid (removed) threads
|
|
CMICmnLLDBDebugSessionInfo::VecActiveThreadId_t::const_iterator it = CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.begin();
|
|
while (it != CMICmnLLDBDebugSessionInfo::Instance().m_vecActiveThreadId.end())
|
|
{
|
|
const MIuint nThreadId = *it;
|
|
lldb::SBThread thread = rProcess.GetThreadAtIndex(nThreadId);
|
|
if (!thread.IsValid())
|
|
{
|
|
// Form MI "=thread-exited,id=\"%ld\",group-id=\"i1\""
|
|
const CMIUtilString strValue(CMIUtilString::Format("%ld", thread.GetIndexID()));
|
|
const CMICmnMIValueConst miValueConst(strValue);
|
|
const CMICmnMIValueResult miValueResult("id", miValueConst);
|
|
CMICmnMIOutOfBandRecord miOutOfBand(CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, miValueResult);
|
|
const CMICmnMIValueConst miValueConst2("i1");
|
|
const CMICmnMIValueResult miValueResult2("group-id", miValueConst2);
|
|
bOk = miOutOfBand.Add(miValueResult2);
|
|
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBand);
|
|
if (!bOk)
|
|
return MIstatus::failure;
|
|
}
|
|
|
|
// Next
|
|
++it;
|
|
}
|
|
|
|
return TextToStdout("(gdb)");
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Take a fully formed MI result record and send to the stdout stream.
|
|
// Also output to the MI Log file.
|
|
// Type: Method.
|
|
// Args: vrMiResultRecord - (R) MI result record object.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::MiResultRecordToStdout(const CMICmnMIResultRecord &vrMiResultRecord)
|
|
{
|
|
return TextToStdout(vrMiResultRecord.GetString());
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Take a fully formed MI Out-of-band record and send to the stdout stream.
|
|
// Also output to the MI Log file.
|
|
// Type: Method.
|
|
// Args: vrMiOutOfBandRecord - (R) MI Out-of-band record object.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::MiOutOfBandRecordToStdout(const CMICmnMIOutOfBandRecord &vrMiOutOfBandRecord)
|
|
{
|
|
return TextToStdout(vrMiOutOfBandRecord.GetString());
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Take a text data and send to the stdout stream. Also output to the MI Log
|
|
// file.
|
|
// Type: Method.
|
|
// Args: vrTxt - (R) Text.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::TextToStdout(const CMIUtilString &vrTxt)
|
|
{
|
|
return CMICmnStreamStdout::TextToStdout(vrTxt);
|
|
}
|
|
|
|
//++ ------------------------------------------------------------------------------------
|
|
// Details: Take a text data and send to the stderr stream. Also output to the MI Log
|
|
// file.
|
|
// Type: Method.
|
|
// Args: vrTxt - (R) Text.
|
|
// Return: MIstatus::success - Functionality succeeded.
|
|
// MIstatus::failure - Functionality failed.
|
|
// Throws: None.
|
|
//--
|
|
bool
|
|
CMICmnLLDBDebuggerHandleEvents::TextToStderr(const CMIUtilString &vrTxt)
|
|
{
|
|
return CMICmnStreamStderr::TextToStderr(vrTxt);
|
|
}
|