Add =shlibs-added/=shlibs-removed notifications (MI)

Summary:
This patch adds =shlibs-added/=shlibs-removed notifications in lldb-mi. In more detail:
# Add Target::ModulesDidLoad/ModulesDidUnload notifications
# Improve Target::TargetEventData:
## Refactoring
## Move it back to include/lldb/Target/Target.h
## Add Target::{GetModuleListFromEvent,GetModuleList}; Add Target::m_module_list
# Add SBModule::{GetSymbolVendorMainFileSpec,GetObjectFileHeaderAddress}
# Add SBTarget::{EventIsTaretEvent,GetTargetFromEvent,GetNumModulesFromEvent,GetModuleAtIndexFromEvent}

All tests pass on OS X.

Reviewers: abidh, zturner, jingham, clayborg

Reviewed By: clayborg

Subscribers: jingham, zturner, lldb-commits, clayborg, abidh

Differential Revision: http://reviews.llvm.org/D8201

llvm-svn: 231858
This commit is contained in:
Ilia K 2015-03-10 21:59:55 +00:00
parent 501d5e9f66
commit eb2c19a549
12 changed files with 391 additions and 79 deletions

View File

@ -78,6 +78,7 @@ protected:
friend class SBBreakpoint;
friend class SBDebugger;
friend class SBProcess;
friend class SBTarget;
friend class SBThread;
friend class SBWatchpoint;

View File

@ -318,6 +318,23 @@ public:
GetVersion (uint32_t *versions,
uint32_t num_versions);
//------------------------------------------------------------------
/// Get accessor for the symbol file specification.
///
/// When debugging an object file an additional debug information can
/// be provided in separate file. Therefore if you debugging something
/// like '/usr/lib/liba.dylib' then debug information can be located
/// in folder like '/usr/lib/liba.dylib.dSYM/'.
///
/// @return
/// A const reference to the file specification object.
//------------------------------------------------------------------
lldb::SBFileSpec
GetSymbolFileSpec() const;
lldb::SBAddress
GetObjectFileHeaderAddress() const;
private:
friend class SBAddress;
friend class SBFrame;

View File

@ -60,7 +60,19 @@ public:
bool
IsValid() const;
static bool
EventIsTargetEvent (const lldb::SBEvent &event);
static lldb::SBTarget
GetTargetFromEvent (const lldb::SBEvent &event);
static uint32_t
GetNumModulesFromEvent (const lldb::SBEvent &event);
static lldb::SBModule
GetModuleAtIndexFromEvent (const uint32_t idx, const lldb::SBEvent &event);
static const char *
GetBroadcasterClassName ();

View File

@ -494,6 +494,57 @@ public:
{
return GetStaticBroadcasterClass();
}
// This event data class is for use by the TargetList to broadcast new target notifications.
class TargetEventData : public EventData
{
public:
TargetEventData (const lldb::TargetSP &target_sp);
TargetEventData (const lldb::TargetSP &target_sp, const ModuleList &module_list);
virtual
~TargetEventData();
static const ConstString &
GetFlavorString ();
virtual const ConstString &
GetFlavor () const
{
return TargetEventData::GetFlavorString ();
}
virtual void
Dump (Stream *s) const;
static const TargetEventData *
GetEventDataFromEvent (const Event *event_ptr);
static lldb::TargetSP
GetTargetFromEvent (const Event *event_ptr);
static ModuleList
GetModuleListFromEvent (const Event *event_ptr);
const lldb::TargetSP &
GetTarget() const
{
return m_target_sp;
}
const ModuleList &
GetModuleList() const
{
return m_module_list;
}
private:
lldb::TargetSP m_target_sp;
ModuleList m_module_list;
DISALLOW_COPY_AND_ASSIGN (TargetEventData);
};
static void
SettingsInitialize ();

View File

@ -685,3 +685,30 @@ SBModule::GetVersion (uint32_t *versions, uint32_t num_versions)
}
}
lldb::SBFileSpec
SBModule::GetSymbolFileSpec() const
{
lldb::SBFileSpec sb_file_spec;
ModuleSP module_sp(GetSP());
if (module_sp)
{
SymbolVendor *symbol_vendor_ptr = module_sp->GetSymbolVendor();
if (symbol_vendor_ptr)
sb_file_spec.SetFileSpec(symbol_vendor_ptr->GetMainFileSpec());
}
return sb_file_spec;
}
lldb::SBAddress
SBModule::GetObjectFileHeaderAddress() const
{
lldb::SBAddress sb_addr;
ModuleSP module_sp (GetSP ());
if (module_sp)
{
ObjectFile *objfile_ptr = module_sp->GetObjectFile();
if (objfile_ptr)
sb_addr.ref() = objfile_ptr->GetHeaderAddress();
}
return sb_addr;
}

View File

@ -13,8 +13,9 @@
#include "lldb/lldb-public.h"
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBBreakpoint.h"
#include "lldb/API/SBDebugger.h"
#include "lldb/API/SBEvent.h"
#include "lldb/API/SBExpressionOptions.h"
#include "lldb/API/SBFileSpec.h"
#include "lldb/API/SBListener.h"
@ -129,6 +130,32 @@ SBTarget::~SBTarget()
{
}
bool
SBTarget::EventIsTargetEvent (const SBEvent &event)
{
return Target::TargetEventData::GetEventDataFromEvent(event.get()) != NULL;
}
SBTarget
SBTarget::GetTargetFromEvent (const SBEvent &event)
{
return Target::TargetEventData::GetTargetFromEvent (event.get());
}
uint32_t
SBTarget::GetNumModulesFromEvent (const SBEvent &event)
{
const ModuleList module_list = Target::TargetEventData::GetModuleListFromEvent (event.get());
return module_list.GetSize();
}
SBModule
SBTarget::GetModuleAtIndexFromEvent (const uint32_t idx, const SBEvent &event)
{
const ModuleList module_list = Target::TargetEventData::GetModuleListFromEvent (event.get());
return SBModule(module_list.GetModuleAtIndex(idx));
}
const char *
SBTarget::GetBroadcasterClassName ()
{

View File

@ -59,76 +59,6 @@
using namespace lldb;
using namespace lldb_private;
namespace {
// This event data class is for use by the TargetList to broadcast new target notifications.
class TargetEventData : public EventData
{
public:
TargetEventData(const lldb::TargetSP &new_target_sp)
: EventData()
, m_target_sp(new_target_sp)
{
}
virtual ~TargetEventData()
{
}
static const ConstString &
GetFlavorString()
{
static ConstString g_flavor("Target::TargetEventData");
return g_flavor;
}
virtual const ConstString &
GetFlavor() const
{
return GetFlavorString();
}
lldb::TargetSP &
GetTarget()
{
return m_target_sp;
}
virtual void
Dump(Stream *s) const
{
}
static const lldb::TargetSP
GetTargetFromEvent(const lldb::EventSP &event_sp)
{
TargetSP target_sp;
const TargetEventData *data = GetEventDataFromEvent (event_sp.get());
if (data)
target_sp = data->m_target_sp;
return target_sp;
}
static const TargetEventData *
GetEventDataFromEvent(const Event *event_ptr)
{
if (event_ptr)
{
const EventData *event_data = event_ptr->GetData();
if (event_data && event_data->GetFlavor() == TargetEventData::GetFlavorString())
return static_cast <const TargetEventData *> (event_ptr->GetData());
}
return nullptr;
}
private:
lldb::TargetSP m_target_sp;
DISALLOW_COPY_AND_ASSIGN (TargetEventData);
};
}
ConstString &
Target::GetStaticBroadcasterClass ()
{
@ -1307,8 +1237,7 @@ Target::ModulesDidLoad (ModuleList &module_list)
{
m_process_sp->ModulesDidLoad (module_list);
}
// TODO: make event data that packages up the module_list
BroadcastEvent (eBroadcastBitModulesLoaded, NULL);
BroadcastEvent (eBroadcastBitModulesLoaded, new TargetEventData (this->shared_from_this(), module_list));
}
}
@ -1328,7 +1257,7 @@ Target::SymbolsDidLoad (ModuleList &module_list)
}
m_breakpoint_list.UpdateBreakpoints (module_list, true, false);
BroadcastEvent(eBroadcastBitSymbolsLoaded, NULL);
BroadcastEvent (eBroadcastBitSymbolsLoaded, new TargetEventData (this->shared_from_this(), module_list));
}
}
@ -1339,8 +1268,7 @@ Target::ModulesDidUnload (ModuleList &module_list, bool delete_locations)
{
UnloadModuleSections (module_list);
m_breakpoint_list.UpdateBreakpoints (module_list, false, delete_locations);
// TODO: make event data that packages up the module_list
BroadcastEvent (eBroadcastBitModulesUnloaded, NULL);
BroadcastEvent (eBroadcastBitModulesUnloaded, new TargetEventData (this->shared_from_this(), module_list));
}
}
@ -3608,3 +3536,69 @@ TargetProperties::DisableSTDIOValueChangedCallback(void *target_property_ptr, Op
else
this_->m_launch_info.GetFlags().Clear(lldb::eLaunchFlagDisableSTDIO);
}
//----------------------------------------------------------------------
// Target::TargetEventData
//----------------------------------------------------------------------
Target::TargetEventData::TargetEventData (const lldb::TargetSP &target_sp) :
EventData (),
m_target_sp (target_sp),
m_module_list ()
{
}
Target::TargetEventData::TargetEventData (const lldb::TargetSP &target_sp, const ModuleList &module_list) :
EventData (),
m_target_sp (target_sp),
m_module_list (module_list)
{
}
Target::TargetEventData::~TargetEventData()
{
}
const ConstString &
Target::TargetEventData::GetFlavorString ()
{
static ConstString g_flavor ("Target::TargetEventData");
return g_flavor;
}
void
Target::TargetEventData::Dump (Stream *s) const
{
}
const Target::TargetEventData *
Target::TargetEventData::GetEventDataFromEvent (const Event *event_ptr)
{
if (event_ptr)
{
const EventData *event_data = event_ptr->GetData();
if (event_data && event_data->GetFlavor() == TargetEventData::GetFlavorString())
return static_cast <const TargetEventData *> (event_ptr->GetData());
}
return NULL;
}
TargetSP
Target::TargetEventData::GetTargetFromEvent (const Event *event_ptr)
{
TargetSP target_sp;
const TargetEventData *event_data = GetEventDataFromEvent (event_ptr);
if (event_data)
target_sp = event_data->m_target_sp;
return target_sp;
}
ModuleList
Target::TargetEventData::GetModuleListFromEvent (const Event *event_ptr)
{
ModuleList module_list;
const TargetEventData *event_data = GetEventDataFromEvent (event_ptr);
if (event_data)
module_list = event_data->m_module_list;
return module_list;
}

View File

@ -293,7 +293,9 @@ CMICmnLLDBDebugger::InitSBListener(void)
}
const CMIUtilString strDbgId("CMICmnLLDBDebugger1");
MIuint eventMask = lldb::SBTarget::eBroadcastBitBreakpointChanged;
MIuint eventMask = lldb::SBTarget::eBroadcastBitBreakpointChanged | lldb::SBTarget::eBroadcastBitModulesLoaded |
lldb::SBTarget::eBroadcastBitModulesUnloaded | lldb::SBTarget::eBroadcastBitWatchpointChanged |
lldb::SBTarget::eBroadcastBitSymbolsLoaded;
bool bOk = RegisterForEvent(strDbgId, CMIUtilString(lldb::SBTarget::GetBroadcasterClassName()), eventMask);
eventMask = lldb::SBThread::eBroadcastBitStackChanged;

View File

@ -20,10 +20,12 @@
//--
// Third party headers:
#include "lldb/API/SBAddress.h"
#include "lldb/API/SBEvent.h"
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBBreakpoint.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBTarget.h"
#include "lldb/API/SBThread.h"
#include "lldb/API/SBCommandInterpreter.h"
#include "lldb/API/SBCommandReturnObject.h"
@ -151,6 +153,11 @@ CMICmnLLDBDebuggerHandleEvents::HandleEvent(const lldb::SBEvent &vEvent, bool &v
vrbHandledEvent = true;
bOk = HandleEventSBThread(vEvent);
}
else if (lldb::SBTarget::EventIsTargetEvent(vEvent))
{
vrbHandledEvent = true;
bOk = HandleEventSBTarget(vEvent);
}
return bOk;
}
@ -567,6 +574,168 @@ CMICmnLLDBDebuggerHandleEvents::HandleEventSBThreadBitStackChanged(const lldb::S
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 MIchar *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 "=shlibs-added,shlib-info=[key=\"value\"...]"
// Type: Method.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleTargetEventBroadcastBitModulesLoaded(const lldb::SBEvent &vEvent)
{
static MIuint s_nModulesLoadedNumber(0);
const MIuint nSize(lldb::SBTarget::GetNumModulesFromEvent(vEvent));
bool bOk = MIstatus::success;
for (MIuint nIndex(0); bOk && (nIndex < nSize); ++nIndex)
{
const lldb::SBModule sbModule = lldb::SBTarget::GetModuleAtIndexFromEvent(nIndex, vEvent);
CMICmnMIValueList miValueList(true);
bOk = MiHelpGetModuleInfo(sbModule, ++s_nModulesLoadedNumber, miValueList);
const CMICmnMIValueResult miValueResult("shlib-info", miValueList);
const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_TargetModulesLoaded, miValueResult);
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
}
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: Print to stdout "=shlibs-removed,shlib-info=[key=\"value\"...]"
// Type: Method.
// Args: None.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::HandleTargetEventBroadcastBitModulesUnloaded(const lldb::SBEvent &vEvent)
{
static MIuint s_nModulesUnloadedNumber(0);
const MIuint nSize(lldb::SBTarget::GetNumModulesFromEvent(vEvent));
bool bOk = MIstatus::success;
for (MIuint nIndex(0); bOk && (nIndex < nSize); ++nIndex)
{
const lldb::SBModule sbModule = lldb::SBTarget::GetModuleAtIndexFromEvent(nIndex, vEvent);
CMICmnMIValueList miValueList(true);
bOk = MiHelpGetModuleInfo(sbModule, ++s_nModulesUnloadedNumber, miValueList);
const CMICmnMIValueResult miValueResult("shlib-info", miValueList);
const CMICmnMIOutOfBandRecord miOutOfBandRecord(CMICmnMIOutOfBandRecord::eOutOfBand_TargetModulesUnloaded, miValueResult);
bOk = bOk && MiOutOfBandRecordToStdout(miOutOfBandRecord);
}
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: Build module information for shlib-info "[num=\"%ld\",name=\"%s\",dyld-addr=\"%#lx\",reason=\"dyld\",path=\"%s\",loaded_addr=\"%#lx\",dsym-objpath=\"%s\"]"
// Type: Method.
// Args: vwrMiValueList - (W) MI value list object.
// Return: MIstatus::success - Functional succeeded.
// MIstatus::failure - Functional failed.
// Throws: None.
//--
bool
CMICmnLLDBDebuggerHandleEvents::MiHelpGetModuleInfo(const lldb::SBModule &vModule, const MIuint nModuleNum,
CMICmnMIValueList &vwrMiValueList)
{
bool bOk = MIstatus::success;
// Build "num" field
const CMIUtilString strNum(CMIUtilString::Format("%ld", nModuleNum));
const CMICmnMIValueConst miValueConst(strNum);
const CMICmnMIValueResult miValueResult("num", miValueConst);
bOk = bOk && vwrMiValueList.Add(miValueResult);
// Build "name" field
const CMICmnMIValueConst miValueConst2(vModule.GetPlatformFileSpec().GetFilename());
const CMICmnMIValueResult miValueResult2("name", miValueConst2);
bOk = bOk && vwrMiValueList.Add(miValueResult2);
// Build "dyld-addr" field
const lldb::SBAddress sbAddress(vModule.GetObjectFileHeaderAddress());
const CMICmnLLDBDebugSessionInfo &rSessionInfo(CMICmnLLDBDebugSessionInfo::Instance());
const lldb::addr_t nLoadAddress(sbAddress.GetLoadAddress(rSessionInfo.GetTarget()));
const CMIUtilString strDyldAddr(CMIUtilString::Format("%#lx", nLoadAddress));
const CMICmnMIValueConst miValueConst3(nLoadAddress != LLDB_INVALID_ADDRESS ? strDyldAddr : "-");
const CMICmnMIValueResult miValueResult3("dyld-addr", miValueConst3);
bOk = bOk && vwrMiValueList.Add(miValueResult3);
// Build "reason" field
const CMICmnMIValueConst miValueConst4("dyld");
const CMICmnMIValueResult miValueResult4("reason", miValueConst4);
bOk = bOk && vwrMiValueList.Add(miValueResult4);
// Build "path" field
char path[PATH_MAX];
vModule.GetPlatformFileSpec().GetPath(path, sizeof(path));
const CMIUtilString strPlatformPath(path);
const CMICmnMIValueConst miValueConst5(strPlatformPath);
const CMICmnMIValueResult miValueResult5("path", miValueConst5);
bOk = bOk && vwrMiValueList.Add(miValueResult5);
// Build "loaded_addr" field
const CMIUtilString strLoadedAddr(CMIUtilString::Format("%#lx", nLoadAddress));
const CMICmnMIValueConst miValueConst6(nLoadAddress != LLDB_INVALID_ADDRESS ? strDyldAddr : "-");
const CMICmnMIValueResult miValueResult6("loaded_addr", miValueConst6);
bOk = bOk && vwrMiValueList.Add(miValueResult6);
// Build "dsym-objpath" field
vModule.GetSymbolFileSpec().GetPath(path, sizeof(path));
const CMIUtilString strSymbolFilePath(path);
if (!CMIUtilString::Compare(strPlatformPath, strSymbolFilePath))
{
const CMICmnMIValueConst miValueConst7(strSymbolFilePath);
const CMICmnMIValueResult miValueResult7("dsym-objpath", miValueConst7);
bOk = bOk && vwrMiValueList.Add(miValueResult7);
}
return bOk;
}
//++ ------------------------------------------------------------------------------------
// Details: Handle a LLDB SBCommandInterpreter event.
// Type: Method.

View File

@ -23,6 +23,7 @@
// In-house headers:
#include "MICmnBase.h"
#include "MICmnMIValueList.h"
#include "MICmnMIValueTuple.h"
#include "MIUtilSingletonBase.h"
@ -66,6 +67,7 @@ class CMICmnLLDBDebuggerHandleEvents : public CMICmnBase, public MI::ISingleton<
bool HandleEventSBBreakpointAdded(const lldb::SBEvent &vEvent);
bool HandleEventSBBreakpointLocationsAdded(const lldb::SBEvent &vEvent);
bool HandleEventSBProcess(const lldb::SBEvent &vEvent);
bool HandleEventSBTarget(const lldb::SBEvent &vEvent);
bool HandleEventSBThread(const lldb::SBEvent &vEvent);
bool HandleEventSBThreadBitStackChanged(const lldb::SBEvent &vEvent);
bool HandleEventSBThreadSuspended(const lldb::SBEvent &vEvent);
@ -79,6 +81,10 @@ class CMICmnLLDBDebuggerHandleEvents : public CMICmnBase, public MI::ISingleton<
bool HandleProcessEventStopSignal(bool &vwrbShouldBrk);
bool HandleProcessEventStopException(void);
bool HandleProcessEventStateSuspended(const lldb::SBEvent &vEvent);
bool HandleTargetEventBroadcastBitModulesLoaded(const lldb::SBEvent &vEvent);
bool HandleTargetEventBroadcastBitModulesUnloaded(const lldb::SBEvent &vEvent);
bool MiHelpGetModuleInfo(const lldb::SBModule &vModule, const MIuint nModuleNum,
CMICmnMIValueList &vwrMiValueList);
bool MiHelpGetCurrentThreadFrame(CMICmnMIValueTuple &vwrMiValueTuple);
bool MiResultRecordToStdout(const CMICmnMIResultRecord &vrMiResultRecord);
bool MiOutOfBandRecordToStdout(const CMICmnMIOutOfBandRecord &vrMiResultRecord);

View File

@ -36,7 +36,9 @@ CMICmnMIOutOfBandRecord::MapOutOfBandToOutOfBandText_t ms_MapOutOfBandToOutOfBan
{CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, "thread-group-started"},
{CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated, "thread-created"},
{CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, "thread-exited"},
{CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected, "thread-selected"}};
{CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected, "thread-selected"},
{CMICmnMIOutOfBandRecord::eOutOfBand_TargetModulesLoaded, "shlibs-added"},
{CMICmnMIOutOfBandRecord::eOutOfBand_TargetModulesUnloaded, "shlibs-removed"}};
CMICmnMIOutOfBandRecord::MapOutOfBandToOutOfBandText_t ms_constMapAsyncRecordTextToToken = {
{CMICmnMIOutOfBandRecord::eOutOfBand_Running, "*"},
{CMICmnMIOutOfBandRecord::eOutOfBand_Stopped, "*"},
@ -49,7 +51,9 @@ CMICmnMIOutOfBandRecord::MapOutOfBandToOutOfBandText_t ms_constMapAsyncRecordTex
{CMICmnMIOutOfBandRecord::eOutOfBand_ThreadGroupStarted, "="},
{CMICmnMIOutOfBandRecord::eOutOfBand_ThreadCreated, "="},
{CMICmnMIOutOfBandRecord::eOutOfBand_ThreadExited, "="},
{CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected, "="}};
{CMICmnMIOutOfBandRecord::eOutOfBand_ThreadSelected, "="},
{CMICmnMIOutOfBandRecord::eOutOfBand_TargetModulesLoaded, "="},
{CMICmnMIOutOfBandRecord::eOutOfBand_TargetModulesUnloaded, "="}};
//++ ------------------------------------------------------------------------------------
// Details: CMICmnMIOutOfBandRecord constructor.

View File

@ -73,6 +73,8 @@ class CMICmnMIOutOfBandRecord : public CMICmnBase
eOutOfBand_ThreadCreated,
eOutOfBand_ThreadExited,
eOutOfBand_ThreadSelected,
eOutOfBand_TargetModulesLoaded,
eOutOfBand_TargetModulesUnloaded,
eOutOfBand_count // Always the last one
};