llvm-project/lldb/tools/lldb-mi/MICmnLLDBDebuggerHandleEvents.cpp
Kate Stone b9c1b51e45 *** This commit represents a complete reformatting of the LLDB source code
*** to conform to clang-format’s LLVM style.  This kind of mass change has
*** two obvious implications:

Firstly, merging this particular commit into a downstream fork may be a huge
effort.  Alternatively, it may be worth merging all changes up to this commit,
performing the same reformatting operation locally, and then discarding the
merge for this particular commit.  The commands used to accomplish this
reformatting were as follows (with current working directory as the root of
the repository):

    find . \( -iname "*.c" -or -iname "*.cpp" -or -iname "*.h" -or -iname "*.mm" \) -exec clang-format -i {} +
    find . -iname "*.py" -exec autopep8 --in-place --aggressive --aggressive {} + ;

The version of clang-format used was 3.9.0, and autopep8 was 1.2.4.

Secondly, “blame” style tools will generally point to this commit instead of
a meaningful prior commit.  There are alternatives available that will attempt
to look through this change and find the appropriate prior commit.  YMMV.

llvm-svn: 280751
2016-09-06 20:57:50 +00:00

1913 lines
73 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.
//
//===----------------------------------------------------------------------===//
// Third party headers:
#include "lldb/API/SBAddress.h"
#include "lldb/API/SBBreakpoint.h"
#include "lldb/API/SBCommandInterpreter.h"
#include "lldb/API/SBCommandReturnObject.h"
#include "lldb/API/SBEvent.h"
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBTarget.h"
#include "lldb/API/SBThread.h"
#include "lldb/API/SBUnixSignals.h"
#ifdef _WIN32
#include <io.h> // For the ::_access()
#else
#include <unistd.h> // For the ::access()
#endif // _WIN32
// In-house headers:
#include "MICmnLLDBDebugSessionInfo.h"
#include "MICmnLLDBDebugger.h"
#include "MICmnLLDBDebuggerHandleEvents.h"
#include "MICmnLog.h"
#include "MICmnMIOutOfBandRecord.h"
#include "MICmnMIResultRecord.h"
#include "MICmnMIValueConst.h"
#include "MICmnMIValueList.h"
#include "MICmnResources.h"
#include "MICmnStreamStderr.h"
#include "MICmnStreamStdout.h"
#include "MIDriver.h"
#include "MIUtilDebug.h"
#include "Platform.h" // for PATH_MAX
//++
//------------------------------------------------------------------------------------
// Details: CMICmnLLDBDebuggerHandleEvents constructor.
// Type: Method.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmnLLDBDebuggerHandleEvents::CMICmnLLDBDebuggerHandleEvents() {}
//++
//------------------------------------------------------------------------------------
// Details: CMICmnLLDBDebuggerHandleEvents destructor.
// Type: Overridable.
// Args: None.
// Return: None.
// Throws: None.
//--
CMICmnLLDBDebuggerHandleEvents::~CMICmnLLDBDebuggerHandleEvents() {
Shutdown();
}
//++
//------------------------------------------------------------------------------------
// Details: Initialize resources for *this broadcaster object.
// Type: Method.
// Args: None.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool CMICmnLLDBDebuggerHandleEvents::Initialize() {
m_clientUsageRefCnt++;
if (m_bInitialized)
return MIstatus::success;
m_bInitialized = MIstatus::success;
m_bSignalsInitialized = false;
m_SIGINT = 0;
m_SIGSTOP = 0;
m_SIGSEGV = 0;
m_SIGTRAP = 0;
return m_bInitialized;
}
//++
//------------------------------------------------------------------------------------
// Details: Release resources for *this broadcaster object.
// Type: Method.
// Args: None.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool CMICmnLLDBDebuggerHandleEvents::Shutdown() {
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 ascertain 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.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool CMICmnLLDBDebuggerHandleEvents::HandleEvent(const lldb::SBEvent &vEvent,
bool &vrbHandledEvent) {
bool bOk = MIstatus::success;
vrbHandledEvent = false;
if (lldb::SBProcess::EventIsProcessEvent(vEvent)) {
vrbHandledEvent = true;
bOk = HandleEventSBProcess(vEvent);
} else if (lldb::SBBreakpoint::EventIsBreakpointEvent(vEvent)) {
vrbHandledEvent = true;
bOk = HandleEventSBBreakPoint(vEvent);
} else if (lldb::SBThread::EventIsThreadEvent(vEvent)) {
vrbHandledEvent = true;
bOk = HandleEventSBThread(vEvent);
} else if (lldb::SBTarget::EventIsTargetEvent(vEvent)) {
vrbHandledEvent = true;
bOk = HandleEventSBTarget(vEvent);
} else if (lldb::SBCommandInterpreter::EventIsCommandInterpreterEvent(
vEvent)) {
vrbHandledEvent = true;
bOk = HandleEventSBCommandInterpreter(vEvent);
}
return bOk;
}
//++
//------------------------------------------------------------------------------------
// Details: Handle a LLDB SBProcess event.
// Type: Method.
// Args: vEvent - (R) An LLDB broadcast event.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBProcess(
const lldb::SBEvent &vEvent) {
bool bOk = MIstatus::success;
const char *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::eBroadcastBitStructuredData:
pEventType = "eBroadcastBitStructuredData";
break;
case lldb::SBProcess::eBroadcastBitStateChanged:
pEventType = "eBroadcastBitStateChanged";
bOk = HandleProcessEventBroadcastBitStateChanged(vEvent);
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 char *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";
bOk = HandleEventSBBreakpointCmn(vEvent);
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%016"
// PRIx64 "\",
// 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);
bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
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 char *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%016"
// PRIx64
// "\",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);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
} 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%016"
// PRIx64
// "\",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);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
}
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 char *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);
miOutOfBandRecord.Add(miValueResult2);
return MiOutOfBandRecordToStdout(miOutOfBandRecord);
}
//++
//------------------------------------------------------------------------------------
// 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 SBTarget event.
// Type: Method.
// Args: vEvent - (R) An LLDB broadcast event.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmnLLDBDebuggerHandleEvents::HandleEventSBTarget(
const lldb::SBEvent &vEvent) {
if (!ChkForStateChanges())
return MIstatus::failure;
bool bOk = MIstatus::success;
const char *pEventType = "";
const MIuint nEventType = vEvent.GetType();
switch (nEventType) {
case lldb::SBTarget::eBroadcastBitBreakpointChanged:
pEventType = "eBroadcastBitBreakpointChanged";
break;
case lldb::SBTarget::eBroadcastBitModulesLoaded:
pEventType = "eBroadcastBitModulesLoaded";
bOk = HandleTargetEventBroadcastBitModulesLoaded(vEvent);
break;
case lldb::SBTarget::eBroadcastBitModulesUnloaded:
pEventType = "eBroadcastBitModulesUnloaded";
bOk = HandleTargetEventBroadcastBitModulesUnloaded(vEvent);
break;
case lldb::SBTarget::eBroadcastBitWatchpointChanged:
pEventType = "eBroadcastBitWatchpointChanged";
break;
case lldb::SBTarget::eBroadcastBitSymbolsLoaded:
pEventType = "eBroadcastBitSymbolsLoaded";
break;
default: {
const CMIUtilString msg(
CMIUtilString::Format(MIRSRC(IDS_LLDBOUTOFBAND_ERR_UNKNOWN_EVENT),
"SBTarget", (MIuint)nEventType));
SetErrorDescription(msg);
return MIstatus::failure;
}
}
m_pLog->WriteLog(CMIUtilString::Format("##### An SBTarget event occurred: %s",
pEventType));
return bOk;
}
//++
//------------------------------------------------------------------------------------
// Details: Print to stdout
// "=library-loaded,id=\"%s\",target-name=\"%s\",host-name=\"%s\",symbols-loaded="%d"[,symbols-path=\"%s\"],loaded_addr=\"0x%016"
// PRIx64"\""
// Type: Method.
// Args: None.
// Return: MIstatus::success - Function succeeded.
// MIstatus::failure - Function failed.
// Throws: None.
//--
bool CMICmnLLDBDebuggerHandleEvents::HandleTargetEventBroadcastBitModulesLoaded(
const lldb::SBEvent &vEvent) {
bool bOk = MIstatus::failure;
const MIuint nSize = lldb::SBTarget::GetNumModulesFromEvent(vEvent);
for (MIuint nIndex = 0; nIndex < nSize; ++nIndex) {
const lldb::SBModule sbModule =
lldb::SBTarget::GetModuleAtIndexFromEvent(nIndex, vEvent);
CMICmnMIOutOfBandRecord miOutOfBandRecord(
CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleLoaded);
const bool bWithExtraFields = true;
bOk = MiHelpGetModuleInfo(sbModule, bWithExtraFields, miOutOfBandRecord);
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
if (!bOk)
break;
}
return bOk;
}
//++
//------------------------------------------------------------------------------------
// Details: Print to stdout
// "=library-unloaded,id=\"%s\",target-name=\"%s\",host-name=\"%s\",symbols-loaded="%d"[,symbols-path=\"%s\"],loaded_addr=\"0x%016"
// PRIx64"\""
// Type: Method.
// Args: None.
// Return: MIstatus::success - Function succeeded.
// MIstatus::failure - Function failed.
// Throws: None.
//--
bool CMICmnLLDBDebuggerHandleEvents::
HandleTargetEventBroadcastBitModulesUnloaded(const lldb::SBEvent &vEvent) {
bool bOk = MIstatus::failure;
const MIuint nSize = lldb::SBTarget::GetNumModulesFromEvent(vEvent);
for (MIuint nIndex = 0; nIndex < nSize; ++nIndex) {
const lldb::SBModule sbModule =
lldb::SBTarget::GetModuleAtIndexFromEvent(nIndex, vEvent);
CMICmnMIOutOfBandRecord miOutOfBandRecord(
CMICmnMIOutOfBandRecord::eOutOfBand_TargetModuleUnloaded);
const bool bWithExtraFields = false;
bOk = MiHelpGetModuleInfo(sbModule, bWithExtraFields, miOutOfBandRecord);
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
if (!bOk)
break;
}
return bOk;
}
//++
//------------------------------------------------------------------------------------
// Details: Build module information for =library-loaded/=library-unloaded:
// "id=\"%s\",target-name=\"%s\",host-name=\"%s\",symbols-loaded="%d"[,symbols-path=\"%s\"],loaded_addr=\"0x%016"
// PRIx64"\""
// Type: Method.
// Args: vwrMiValueList - (W) MI value list object.
// Return: MIstatus::success - Function succeeded.
// MIstatus::failure - Function failed.
// Throws: None.
//--
bool CMICmnLLDBDebuggerHandleEvents::MiHelpGetModuleInfo(
const lldb::SBModule &vModule, const bool vbWithExtraFields,
CMICmnMIOutOfBandRecord &vwrMiOutOfBandRecord) {
bool bOk = MIstatus::success;
// First, build standard fields:
// Build "id" field
std::unique_ptr<char[]> apPath(new char[PATH_MAX]);
vModule.GetFileSpec().GetPath(apPath.get(), PATH_MAX);
const CMIUtilString strTargetPath(apPath.get());
const CMICmnMIValueConst miValueConst(strTargetPath.AddSlashes());
const CMICmnMIValueResult miValueResult("id", miValueConst);
vwrMiOutOfBandRecord.Add(miValueResult);
// Build "target-name" field
const CMICmnMIValueConst miValueConst2(strTargetPath.AddSlashes());
const CMICmnMIValueResult miValueResult2("target-name", miValueConst2);
vwrMiOutOfBandRecord.Add(miValueResult2);
// Build "host-name" field
vModule.GetPlatformFileSpec().GetPath(apPath.get(), PATH_MAX);
const CMIUtilString strHostPath(apPath.get());
const CMICmnMIValueConst miValueConst3(strHostPath.AddSlashes());
const CMICmnMIValueResult miValueResult3("host-name", miValueConst3);
vwrMiOutOfBandRecord.Add(miValueResult3);
// Then build extra fields if needed:
if (vbWithExtraFields) {
// Build "symbols-loaded" field
vModule.GetSymbolFileSpec().GetPath(apPath.get(), PATH_MAX);
const CMIUtilString strSymbolsPath(apPath.get());
const bool bSymbolsLoaded =
!CMIUtilString::Compare(strHostPath, strSymbolsPath);
const CMICmnMIValueConst miValueConst4(
CMIUtilString::Format("%d", bSymbolsLoaded));
const CMICmnMIValueResult miValueResult4("symbols-loaded", miValueConst4);
vwrMiOutOfBandRecord.Add(miValueResult4);
// Build "symbols-path" field
if (bSymbolsLoaded) {
const CMICmnMIValueConst miValueConst5(strSymbolsPath.AddSlashes());
const CMICmnMIValueResult miValueResult5("symbols-path", miValueConst5);
vwrMiOutOfBandRecord.Add(miValueResult5);
}
// Build "loaded_addr" field
lldb::SBAddress sbAddress(vModule.GetObjectFileHeaderAddress());
CMICmnLLDBDebugSessionInfo &rSessionInfo(
CMICmnLLDBDebugSessionInfo::Instance());
const lldb::addr_t nLoadAddress(
sbAddress.GetLoadAddress(rSessionInfo.GetTarget()));
const CMIUtilString strLoadedAddr(
nLoadAddress != LLDB_INVALID_ADDRESS
? CMIUtilString::Format("0x%016" PRIx64, nLoadAddress)
: "-");
const CMICmnMIValueConst miValueConst6(strLoadedAddr);
const CMICmnMIValueResult miValueResult6("loaded_addr", miValueConst6);
vwrMiOutOfBandRecord.Add(miValueResult6);
// Build "size" field
lldb::SBSection sbSection = sbAddress.GetSection();
const CMIUtilString strSize(
CMIUtilString::Format("%" PRIu64, sbSection.GetByteSize()));
const CMICmnMIValueConst miValueConst7(strSize);
const CMICmnMIValueResult miValueResult7("size", miValueConst7);
vwrMiOutOfBandRecord.Add(miValueResult7);
}
return bOk;
}
//++
//------------------------------------------------------------------------------------
// 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 char *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";
const bool bForceExit = true;
CMICmnLLDBDebugger::Instance().GetDriver().SetExitApplicationFlag(
bForceExit);
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.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventBroadcastBitStateChanged(
const lldb::SBEvent &vEvent) {
// Make sure the program hasn't been auto-restarted:
if (lldb::SBProcess::GetRestartedFromEvent(vEvent))
return MIstatus::success;
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 char *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(vEvent, 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:
// Don't exit from lldb-mi here. We should be able to re-run target.
pEventType = "eStateExited";
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) {
bool bOk = MIstatus::success;
lldb::SBDebugger &rDebugger =
CMICmnLLDBDebugSessionInfo::Instance().GetDebugger();
lldb::SBProcess sbProcess =
CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
lldb::SBTarget target = sbProcess.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(
const lldb::SBEvent &vrEvent, bool &vwrbShouldBrk) {
if (!UpdateSelectedThread())
return MIstatus::failure;
const char *pEventType = "";
bool bOk = MIstatus::success;
lldb::SBProcess sbProcess =
CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
const lldb::StopReason eStoppedReason =
sbProcess.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(vrEvent);
break;
case lldb::eStopReasonException:
pEventType = "eStopReasonException";
bOk = HandleProcessEventStopException();
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: vrEvent - (R) An LLDB broadcast event.
// Return: MIstatus::success - Functionality succeeded.
// MIstatus::failure - Functionality failed.
// Throws: None.
//--
bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopSignal(
const lldb::SBEvent &vrEvent) {
bool bOk = MIstatus::success;
InitializeSignals();
lldb::SBProcess sbProcess =
CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
const MIuint64 nStopReason =
sbProcess.GetSelectedThread().GetStopReasonDataAtIndex(0);
const bool bInterrupted = lldb::SBProcess::GetInterruptedFromEvent(vrEvent);
if (nStopReason == m_SIGINT || (nStopReason == m_SIGSTOP && bInterrupted)) {
// MI print
// "*stopped,reason=\"signal-received\",signal-name=\"SIGINT\",signal-meaning=\"Interrupt\",frame={%s},thread-id=\"%d\",stopped-threads=\"all\""
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);
miOutOfBandRecord.Add(miValueResult2);
const CMICmnMIValueConst miValueConst3("Interrupt");
const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3);
miOutOfBandRecord.Add(miValueResult3);
CMICmnMIValueTuple miValueTuple;
bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple);
const CMICmnMIValueResult miValueResult4("frame", miValueTuple);
miOutOfBandRecord.Add(miValueResult4);
const CMIUtilString strThreadId(CMIUtilString::Format(
"%" PRIu32, sbProcess.GetSelectedThread().GetIndexID()));
const CMICmnMIValueConst miValueConst5(strThreadId);
const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5);
miOutOfBandRecord.Add(miValueResult5);
const CMICmnMIValueConst miValueConst6("all");
const CMICmnMIValueResult miValueResult6("stopped-threads", miValueConst6);
miOutOfBandRecord.Add(miValueResult6);
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
} else if (nStopReason == m_SIGSTOP) {
// MI print
// "*stopped,reason=\"signal-received\",signal-name=\"SIGSTOP\",signal-meaning=\"Stop\",frame={%s},thread-id=\"%d\",stopped-threads=\"all\""
const CMICmnMIValueConst miValueConst("signal-received");
const CMICmnMIValueResult miValueResult("reason", miValueConst);
CMICmnMIOutOfBandRecord miOutOfBandRecord(
CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
const CMICmnMIValueConst miValueConst2("SIGSTOP");
const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2);
miOutOfBandRecord.Add(miValueResult2);
const CMICmnMIValueConst miValueConst3("Stop");
const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3);
miOutOfBandRecord.Add(miValueResult3);
CMICmnMIValueTuple miValueTuple;
bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple);
const CMICmnMIValueResult miValueResult4("frame", miValueTuple);
miOutOfBandRecord.Add(miValueResult4);
const CMIUtilString strThreadId(CMIUtilString::Format(
"%" PRIu32, sbProcess.GetSelectedThread().GetIndexID()));
const CMICmnMIValueConst miValueConst5(strThreadId);
const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5);
miOutOfBandRecord.Add(miValueResult5);
const CMICmnMIValueConst miValueConst6("all");
const CMICmnMIValueResult miValueResult6("stopped-threads", miValueConst6);
miOutOfBandRecord.Add(miValueResult6);
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
} else if (nStopReason == m_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);
miOutOfBandRecord.Add(miValueResult2);
const CMICmnMIValueConst miValueConst3("Segmentation fault");
const CMICmnMIValueResult miValueResult3("signal-meaning", miValueConst3);
miOutOfBandRecord.Add(miValueResult3);
CMICmnMIValueTuple miValueTuple;
bOk = bOk && MiHelpGetCurrentThreadFrame(miValueTuple);
const CMICmnMIValueResult miValueResult4("frame", miValueTuple);
miOutOfBandRecord.Add(miValueResult4);
const CMIUtilString strThreadId(CMIUtilString::Format(
"%d", sbProcess.GetSelectedThread().GetIndexID()));
const CMICmnMIValueConst miValueConst5(strThreadId);
const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5);
miOutOfBandRecord.Add(miValueResult5);
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
// Note no "(gdb)" output here
} else if (nStopReason == m_SIGTRAP) {
lldb::SBThread thread = sbProcess.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 (sbProcess.IsValid())
sbProcess.Continue();
}
}
}
} else {
// MI print
// "*stopped,reason=\"signal-received\",signal-name=\"%s\",thread-id=\"%d\",stopped-threads=\"all\""
// MI print
// "*stopped,reason=\"signal-received\",signal=\"%d\",thread-id=\"%d\",stopped-threads=\"all\""
const CMICmnMIValueConst miValueConst("signal-received");
const CMICmnMIValueResult miValueResult("reason", miValueConst);
CMICmnMIOutOfBandRecord miOutOfBandRecord(
CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
lldb::SBUnixSignals sbUnixSignals = sbProcess.GetUnixSignals();
const char *pSignal = sbUnixSignals.GetSignalAsCString(nStopReason);
if (pSignal) {
const CMICmnMIValueConst miValueConst2(pSignal);
const CMICmnMIValueResult miValueResult2("signal-name", miValueConst2);
miOutOfBandRecord.Add(miValueResult2);
} else {
const CMIUtilString strSignal(
CMIUtilString::Format("%" PRIu64, nStopReason));
const CMICmnMIValueConst miValueConst2(strSignal);
const CMICmnMIValueResult miValueResult2("signal", miValueConst2);
miOutOfBandRecord.Add(miValueResult2);
}
const CMIUtilString strThreadId(CMIUtilString::Format(
"%d", sbProcess.GetSelectedThread().GetIndexID()));
const CMICmnMIValueConst miValueConst3(strThreadId);
const CMICmnMIValueResult miValueResult3("thread-id", miValueConst3);
miOutOfBandRecord.Add(miValueResult3);
const CMICmnMIValueConst miValueConst4("all");
const CMICmnMIValueResult miValueResult4("stopped-threads", miValueConst4);
miOutOfBandRecord.Add(miValueResult4);
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
}
return bOk;
}
//++
//------------------------------------------------------------------------------------
// Details: Asynchronous event handler for LLDB Process stop exception.
// Type: Method.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool CMICmnLLDBDebuggerHandleEvents::HandleProcessEventStopException() {
const lldb::SBProcess sbProcess =
CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
lldb::SBThread sbThread = sbProcess.GetSelectedThread();
const size_t nStopDescriptionLen = sbThread.GetStopDescription(nullptr, 0);
std::unique_ptr<char[]> apStopDescription(new char[nStopDescriptionLen]);
sbThread.GetStopDescription(apStopDescription.get(), nStopDescriptionLen);
// MI print
// "*stopped,reason=\"exception-received\",exception=\"%s\",thread-id=\"%d\",stopped-threads=\"all\""
const CMICmnMIValueConst miValueConst("exception-received");
const CMICmnMIValueResult miValueResult("reason", miValueConst);
CMICmnMIOutOfBandRecord miOutOfBandRecord(
CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, miValueResult);
const CMIUtilString strReason(apStopDescription.get());
const CMICmnMIValueConst miValueConst2(strReason);
const CMICmnMIValueResult miValueResult2("exception", miValueConst2);
miOutOfBandRecord.Add(miValueResult2);
const CMIUtilString strThreadId(
CMIUtilString::Format("%d", sbThread.GetIndexID()));
const CMICmnMIValueConst miValueConst3(strThreadId);
const CMICmnMIValueResult miValueResult3("thread-id", miValueConst3);
miOutOfBandRecord.Add(miValueResult3);
const CMICmnMIValueConst miValueConst4("all");
const CMICmnMIValueResult miValueResult4("stopped-threads", miValueConst4);
miOutOfBandRecord.Add(miValueResult4);
bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
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 sbProcess =
CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
lldb::SBThread thread = sbProcess.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, CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_NoArguments,
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() {
// 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 sbProcess =
CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
const MIuint64 brkPtId =
sbProcess.GetSelectedThread().GetStopReasonDataAtIndex(0);
lldb::SBBreakpoint brkPt =
CMICmnLLDBDebugSessionInfo::Instance().GetTarget().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 sbProcess =
CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
lldb::SBThread thread = sbProcess.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);
miOutOfBandRecord.Add(miValueResult2);
const CMIUtilString strBkp(CMIUtilString::Format("%d", vBrkPtId));
const CMICmnMIValueConst miValueConst3(strBkp);
CMICmnMIValueResult miValueResult3("bkptno", miValueConst3);
miOutOfBandRecord.Add(miValueResult3);
const CMICmnMIValueConst miValueConst4("{}");
const CMICmnMIValueResult miValueResult4("frame", miValueConst4);
miOutOfBandRecord.Add(miValueResult4);
const CMIUtilString strThreadId(
CMIUtilString::Format("%d", vBrkPt.GetThreadIndex()));
const CMICmnMIValueConst miValueConst5(strThreadId);
const CMICmnMIValueResult miValueResult5("thread-id", miValueConst5);
miOutOfBandRecord.Add(miValueResult5);
const CMICmnMIValueConst miValueConst6("all");
const CMICmnMIValueResult miValueResult6("stopped-threads", miValueConst6);
miOutOfBandRecord.Add(miValueResult6);
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
return bOk;
}
CMICmnLLDBDebugSessionInfo &rSessionInfo(
CMICmnLLDBDebugSessionInfo::Instance());
// MI print
// "*stopped,reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"%d\",frame={addr=\"0x%016"
// PRIx64
// "\",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);
miOutOfBandRecord.Add(miValueResultA);
const CMIUtilString strBkp(CMIUtilString::Format("%d", vBrkPtId));
const CMICmnMIValueConst miValueConstB(strBkp);
CMICmnMIValueResult miValueResultB("bkptno", miValueConstB);
miOutOfBandRecord.Add(miValueResultB);
// frame={addr=\"0x%016" PRIx64
// "\",func=\"%s\",args=[],file=\"%s\",fullname=\"%s\",line=\"%d\"}
if (bOk) {
CMICmnMIValueTuple miValueTuple;
bOk = bOk &&
rSessionInfo.MIResponseFormFrameInfo(
thread, 0,
CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_AllArguments,
miValueTuple);
const CMICmnMIValueResult miValueResult8("frame", miValueTuple);
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);
miOutOfBandRecord.Add(miValueResult8);
}
if (bOk) {
const CMICmnMIValueConst miValueConst9("all");
const CMICmnMIValueResult miValueResult9("stopped-threads", miValueConst9);
miOutOfBandRecord.Add(miValueResult9);
bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
}
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() {
bool bOk = true;
lldb::SBProcess sbProcess =
CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
lldb::SBThread thread = sbProcess.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);
miOutOfBandRecord.Add(miValueResult2);
bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
return bOk;
}
CMICmnLLDBDebugSessionInfo &rSessionInfo(
CMICmnLLDBDebugSessionInfo::Instance());
// MI print
// "*stopped,reason=\"end-stepping-range\",frame={addr=\"0x%016" PRIx64
// "\",func=\"%s\",args=[\"%s\"],file=\"%s\",fullname=\"%s\",line=\"%d\"},thread-id=\"%d\",stopped-threads=\"all\""
// Function args
CMICmnMIValueTuple miValueTuple;
if (!rSessionInfo.MIResponseFormFrameInfo(
thread, 0, CMICmnLLDBDebugSessionInfo::eFrameInfoFormat_AllArguments,
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);
miOutOfBandRecord.Add(miValueResult2);
// Add to MI thread-id=\"%d\",stopped-threads=\"all\"
const CMIUtilString strThreadId(
CMIUtilString::Format("%d", thread.GetIndexID()));
const CMICmnMIValueConst miValueConst8(strThreadId);
const CMICmnMIValueResult miValueResult8("thread-id", miValueConst8);
miOutOfBandRecord.Add(miValueResult8);
const CMICmnMIValueConst miValueConst9("all");
const CMICmnMIValueResult miValueResult9("stopped-threads", miValueConst9);
miOutOfBandRecord.Add(miValueResult9);
bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
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() {
lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance()
.GetDebugger()
.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() {
CMICmnMIValueConst miValueConst("all");
CMICmnMIValueResult miValueResult("thread-id", miValueConst);
CMICmnMIOutOfBandRecord miOutOfBandRecord(
CMICmnMIOutOfBandRecord::eOutOfBand_Running, miValueResult);
bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
bOk = bOk && CMICmnStreamStdout::WritePrompt();
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() {
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);
miOutOfBandRecord.Add(miValueResult2);
bool 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);
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 && CMICmnStreamStdout::WritePrompt();
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() {
CMIUtilString text;
std::unique_ptr<char[]> apStdoutBuffer(new char[1024]);
lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance()
.GetDebugger()
.GetSelectedTarget()
.GetProcess();
while (1) {
const size_t nBytes = process.GetSTDOUT(apStdoutBuffer.get(), 1024);
text.append(apStdoutBuffer.get(), nBytes);
while (1) {
const size_t nNewLine = text.find('\n');
if (nNewLine == std::string::npos)
break;
const CMIUtilString line(text.substr(0, nNewLine + 1));
text.erase(0, nNewLine + 1);
const bool bEscapeQuotes(true);
CMICmnMIValueConst miValueConst(line.Escape(bEscapeQuotes));
CMICmnMIOutOfBandRecord miOutOfBandRecord(
CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput, miValueConst);
const bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
if (!bOk)
return MIstatus::failure;
}
if (nBytes == 0) {
if (!text.empty()) {
const bool bEscapeQuotes(true);
CMICmnMIValueConst miValueConst(text.Escape(bEscapeQuotes));
CMICmnMIOutOfBandRecord miOutOfBandRecord(
CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput,
miValueConst);
return MiOutOfBandRecordToStdout(miOutOfBandRecord);
}
break;
}
}
return MIstatus::success;
}
//++
//------------------------------------------------------------------------------------
// 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() {
CMIUtilString text;
std::unique_ptr<char[]> apStderrBuffer(new char[1024]);
lldb::SBProcess process = CMICmnLLDBDebugSessionInfo::Instance()
.GetDebugger()
.GetSelectedTarget()
.GetProcess();
while (1) {
const size_t nBytes = process.GetSTDERR(apStderrBuffer.get(), 1024);
text.append(apStderrBuffer.get(), nBytes);
while (1) {
const size_t nNewLine = text.find('\n');
if (nNewLine == std::string::npos)
break;
const CMIUtilString line(text.substr(0, nNewLine + 1));
const bool bEscapeQuotes(true);
CMICmnMIValueConst miValueConst(line.Escape(bEscapeQuotes));
CMICmnMIOutOfBandRecord miOutOfBandRecord(
CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput, miValueConst);
const bool bOk = MiOutOfBandRecordToStdout(miOutOfBandRecord);
if (!bOk)
return MIstatus::failure;
}
if (nBytes == 0) {
if (!text.empty()) {
const bool bEscapeQuotes(true);
CMICmnMIValueConst miValueConst(text.Escape(bEscapeQuotes));
CMICmnMIOutOfBandRecord miOutOfBandRecord(
CMICmnMIOutOfBandRecord::eOutOfBand_TargetStreamOutput,
miValueConst);
return MiOutOfBandRecordToStdout(miOutOfBandRecord);
}
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() {
CMICmnLLDBDebugSessionInfo &rSessionInfo(
CMICmnLLDBDebugSessionInfo::Instance());
lldb::SBProcess sbProcess = rSessionInfo.GetProcess();
if (!sbProcess.IsValid())
return MIstatus::success;
// Check for created threads
const MIuint nThread = sbProcess.GetNumThreads();
for (MIuint i = 0; i < nThread; i++) {
// GetThreadAtIndex() uses a base 0 index
// GetThreadByIndexID() uses a base 1 index
lldb::SBThread thread = sbProcess.GetThreadAtIndex(i);
if (!thread.IsValid())
continue;
const MIuint threadIndexID = thread.GetIndexID();
const bool bFound =
std::find(rSessionInfo.m_vecActiveThreadId.cbegin(),
rSessionInfo.m_vecActiveThreadId.cend(),
threadIndexID) != rSessionInfo.m_vecActiveThreadId.end();
if (!bFound) {
rSessionInfo.m_vecActiveThreadId.push_back(threadIndexID);
// Form MI "=thread-created,id=\"%d\",group-id=\"i1\""
const CMIUtilString strValue(CMIUtilString::Format("%d", threadIndexID));
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);
miOutOfBand.Add(miValueResult2);
bool bOk = MiOutOfBandRecordToStdout(miOutOfBand);
if (!bOk)
return MIstatus::failure;
}
}
lldb::SBThread currentThread = sbProcess.GetSelectedThread();
if (currentThread.IsValid()) {
const MIuint currentThreadIndexID = currentThread.GetIndexID();
if (rSessionInfo.m_currentSelectedThread != currentThreadIndexID) {
rSessionInfo.m_currentSelectedThread = currentThreadIndexID;
// Form MI "=thread-selected,id=\"%d\""
const CMIUtilString strValue(
CMIUtilString::Format("%d", currentThreadIndexID));
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::iterator it =
rSessionInfo.m_vecActiveThreadId.begin();
while (it != rSessionInfo.m_vecActiveThreadId.end()) {
const MIuint threadIndexID = *it;
lldb::SBThread thread = sbProcess.GetThreadByIndexID(threadIndexID);
if (!thread.IsValid()) {
// Form MI "=thread-exited,id=\"%ld\",group-id=\"i1\""
const CMIUtilString strValue(CMIUtilString::Format("%ld", threadIndexID));
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);
miOutOfBand.Add(miValueResult2);
bool bOk = MiOutOfBandRecordToStdout(miOutOfBand);
if (!bOk)
return MIstatus::failure;
// Remove current thread from cache and get next
it = rSessionInfo.m_vecActiveThreadId.erase(it);
} else
// Next
++it;
}
return CMICmnStreamStdout::WritePrompt();
}
//++
//------------------------------------------------------------------------------------
// 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);
}
//++
//------------------------------------------------------------------------------------
// Details: Initialize the member variables with the signal values in this
// process
// file.
// Type: Method.
// Args: None
// Return: Noen
// Throws: None.
//--
void CMICmnLLDBDebuggerHandleEvents::InitializeSignals() {
if (!m_bSignalsInitialized) {
lldb::SBProcess sbProcess =
CMICmnLLDBDebugSessionInfo::Instance().GetProcess();
if (sbProcess.IsValid()) {
lldb::SBUnixSignals unix_signals = sbProcess.GetUnixSignals();
m_SIGINT = unix_signals.GetSignalNumberFromName("SIGINT");
m_SIGSTOP = unix_signals.GetSignalNumberFromName("SIGSTOP");
m_SIGSEGV = unix_signals.GetSignalNumberFromName("SIGSEGV");
m_SIGTRAP = unix_signals.GetSignalNumberFromName("SIGTRAP");
m_bSignalsInitialized = true;
}
}
}