Update the Windows debug agent: hardware watchpoint support, better
thread management, better exception handling.
diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/EventClientNotifier.cpp b/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/EventClientNotifier.cpp
index 9aa44a7..bddea0b 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/EventClientNotifier.cpp
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/common_agent/EventClientNotifier.cpp
@@ -131,7 +131,8 @@
 	out.writeString(eventParams->context->GetID());

 	out.writeZero();

 

-	out.writeLong(eventParams->pcAddress);

+	// writeULong instead of writeLong so we won't send a negative address.

+	out.writeULong(eventParams->pcAddress);

 	out.writeZero();

 

 	out.writeString(REASON_SHAREDLIB);

@@ -175,7 +176,8 @@
 	out.writeString(params->context->GetID().c_str());

 	out.writeZero();

 

-	out.writeLong(params->pcAddress);

+	// writeULong instead of writeLong so we won't send a negative address.

+	out.writeULong(params->pcAddress);

 	out.writeZero();

 

 	out.writeString(params->reason);

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/tcf_agent/framework/errors.c b/org.eclipse.cdt.debug.edc.windows.agent/src/tcf_agent/framework/errors.c
index 1eb6066..2015d41 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/tcf_agent/framework/errors.c
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/tcf_agent/framework/errors.c
@@ -347,9 +347,9 @@
     case ERR_CACHE_MISS:         return "Invalid data cache state";
     case ERR_NOT_ACTIVE:         return "Context is not active";
     case ERR_HWBRK_NOT_SET:      return "Cannot set hardware breakpoint";
-    case ERR_HWBRK_INVALID_SIZE: return "Invalid size";
-    case ERR_HWBRK_NO_RESOURCES: return "No resources available";
-    case ERR_HWBRK_NOT_ALIGNED:  return "Invalid address alignment";
+    case ERR_HWBRK_INVALID_SIZE: return "Invalid hardware breakpoint size";
+    case ERR_HWBRK_NO_RESOURCES: return "No hardware breakpoint resources available";
+    case ERR_HWBRK_NOT_ALIGNED:  return "Invalid hardware breakpoint address alignment";
     case ERR_HWBRK_INVALID_MODE: return "Invalid hardware breakpoint mode";
     case ERR_PGPRO_UNSET:        return "Cannot set page protection";
     case ERR_PGPRO_UNRESET:      return "Cannot reset page protection";
diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/SettingsService.cpp b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/SettingsService.cpp
index 0a682ad..c4a4c9a 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/SettingsService.cpp
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/SettingsService.cpp
@@ -59,7 +59,7 @@
 	TCFService(proto) {

 	allowFilenameMatch = false;

 	enableDebugStringLogging = true;

-	exceptionsBitmask = 0x00000000L; // no exceptions reported by default

+	exceptionsBitmask = 0xffffffffL; // report all exception by default

 

     AddCommand("get", command_get_settings);		// compatibility -- not used

     AddCommand("getIds", command_get_settings);

@@ -168,7 +168,9 @@
  */

 void SettingsService::debugSessionEnds()

 {

+	// reset to default.

 	modulesToDebug.clear();

+    exceptionsBitmask = 0xffffffffL; // report all exception by default

 }

 

 bool SettingsService::reportDebugEventForModule(std::string module)

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinDebugMonitor.cpp b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinDebugMonitor.cpp
index 32c63d3..e75a192 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinDebugMonitor.cpp
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinDebugMonitor.cpp
@@ -628,13 +628,14 @@
 	if (process) {

 		WinThread* thread = new WinThread(*process, debugEvent);

 		thread->SetDebugging(true);

+		thread->DuplicateDebugRegisters();

 		ContextManager::addContext(thread);

 		EventClientNotifier::SendContextAdded(thread);

 	} else {

 		assert(false);

 	}

 

-	ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);

+	::ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);

 }

 

 void WinDebugMonitor::HandleProcessExitedEvent(DEBUG_EVENT& debugEvent)

@@ -680,25 +681,19 @@
 	unsigned long baseOfCode = 0;

 	std::string moduleName = GetExecutableInfo(debugEvent.u.LoadDll.hFile, baseOfCode, codeSize);

 

-	if (SettingsService::reportDebugEventForModule(moduleName))

-	{

-		LogTrace("DebugProcessMonitor::HandleDLLLoadedEvent", "Base address: %8.8x %s", debugEvent.u.LoadDll.lpBaseOfDll, moduleName.c_str());

-		WinThread* thread = WinThread::GetThreadByID(debugEvent.dwProcessId, debugEvent.dwThreadId);

-		if (thread) {

-			thread->HandleExecutableEvent(true, moduleName, (unsigned long)debugEvent.u.LoadDll.lpBaseOfDll, codeSize);

-		}

-	}

-	else

-	{

+	CloseHandle(debugEvent.u.LoadDll.hFile);

+

+	LogTrace("DebugProcessMonitor::HandleDLLLoadedEvent", "Base address: %8.8x %s", debugEvent.u.LoadDll.lpBaseOfDll, moduleName.c_str());

+	WinThread* thread = WinThread::GetThreadByID(debugEvent.dwProcessId, debugEvent.dwThreadId);

+	if (thread) {

+		thread->HandleExecutableEvent(true, moduleName, (unsigned long)debugEvent.u.LoadDll.lpBaseOfDll, codeSize);

+	} else {

 		ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);

 	}

-

-	CloseHandle(debugEvent.u.LoadDll.hFile);

 }

 

 void WinDebugMonitor::HandleDLLUnloadedEvent(DEBUG_EVENT& debugEvent)

 {

-	// if our process knows about this dll then it must be in the list of modules to debug

 	WinProcess* process = WinProcess::GetProcessByID(debugEvent.dwProcessId);

 	if (process)

 	{

@@ -708,10 +703,13 @@
 			WinThread* thread = WinThread::GetThreadByID(debugEvent.dwProcessId, debugEvent.dwThreadId);

 			if (thread) {

 				thread->HandleExecutableEvent(false, "", (unsigned long)debugEvent.u.UnloadDll.lpBaseOfDll, 0);

+				// HandleExecutableEvent will decide if we need to continue the debug event or not, so return

+				return;

 			}

 		}

 	}

 

+	// we get here if the event wasn't passed onto the thread to handle

 	ContinueDebugEvent(debugEvent.dwProcessId, debugEvent.dwThreadId, DBG_CONTINUE);

 }

 

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinHWBkptMgr.cpp b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinHWBkptMgr.cpp
index 3c3e7b1..04e5705 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinHWBkptMgr.cpp
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinHWBkptMgr.cpp
@@ -172,11 +172,11 @@
 	return MAX_HWBP - InUseCount();

 }

 

-WinHWBkptMgr::DRMask WinHWBkptMgr::UseUnusedRegister() {

-	if (!(DR0 & inUse))	{	inUse |= DR0; return DR0;	}

-	if (!(DR1 & inUse))	{	inUse |= DR1; return DR1;	}

-	if (!(DR2 & inUse))	{	inUse |= DR2; return DR2;	}

-	if (!(DR3 & inUse))	{	inUse |= DR3; return DR3;	}

+WinHWBkptMgr::DRNum WinHWBkptMgr::UseUnusedRegister() {

+	if (!(DR0 & inUse))	{	inUse |= DR0; return 0;	}

+	if (!(DR1 & inUse))	{	inUse |= DR1; return 1;	}

+	if (!(DR2 & inUse))	{	inUse |= DR2; return 2;	}

+	if (!(DR3 & inUse))	{	inUse |= DR3; return 3;	}

 	return 0;

 }

 

@@ -223,8 +223,8 @@
 	hwBkpt[wp].tcfBp = bp;

 	hwBkpt[wp].accessMode = hwMode;

 	for (;reqdRegs > 0;--reqdRegs) {

-		DRMask dr = UseUnusedRegister();

-		hwBkpt[wp].inUse |= dr;

+		DRNum dr = UseUnusedRegister();

+		hwBkpt[wp].inUse |= 1 << dr;

 

 		unsigned char drSz;	// size to set in DR register

 		switch (locAddr & 7) {

@@ -240,7 +240,9 @@
 		// these are shifted inside based on the reg used

 		DRFlags dr7bits = sDR7SizeBitsMap(drSz) | hwBkpt[wp].accessMode;

 

-		bp->process->SetDebugRegister(dr, locAddr, dr7bits);

+		hwBkpt[wp].dbgReg[dr].address = locAddr;

+		hwBkpt[wp].dbgReg[dr].flags = dr7bits;

+		bp->process->SetDebugRegister(dr, hwBkpt[wp].dbgReg[dr]);

 

 		locAddr += drSz;

 		locSize -= drSz;

@@ -256,16 +258,13 @@
 	AgentBreakID& wp = bp->agentBreakID;

 	if (wp == AGENT_BREAK_UNSET)

 		return ERR_HWBRK_NOT_SET;

-	for (int i = 0; i < MAX_HWBP; ++i) {

-		DRMask dr = 1 << i;

-		if (hwBkpt[wp].inUse & dr) {

-			inUse &= ~dr;

-			bp->process->ClearDebugRegister(dr);

-		}

-	}

+

+	DRMask& wpInUse = hwBkpt[wp].inUse;

+	bp->process->ClearDebugRegisters(wpInUse);

+	inUse &= ~wpInUse;

+	wpInUse = 0;

 

 	hwBkpt[wp].tcfBp = NULL;

-	hwBkpt[wp].inUse = 0;

 	bp->process = NULL;

 	wp = AGENT_BREAK_UNSET;

 	return 0;

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinHWBkptMgr.h b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinHWBkptMgr.h
index 930f303..8cd1bf0 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinHWBkptMgr.h
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinHWBkptMgr.h
@@ -71,8 +71,9 @@
 

 		WinHWBkptMgr();

 

-	typedef unsigned char DRMask;

 	typedef unsigned char DRFlags;

+	typedef unsigned char DRMask;

+	typedef unsigned char DRNum;

 

 	int SetHardwareBreak(TBreakpoint*);

 	int ClearHardwareBreak(TBreakpoint*);

@@ -86,10 +87,16 @@
 	static const Mode readwrite	= 0x03;

 	static const Mode invalid	= 0x04;

 

+	struct DbgRegInfo {

+		ContextAddress	address;

+		DRFlags 		flags;

+	};

+

 	struct HWBreakInfo {

 		TBreakpoint*	tcfBp;

 		DRMask			inUse;		// mask of the regs used for this hw-break

 		Mode			accessMode;	// accessMode to use for all regs used

+		DbgRegInfo		dbgReg[MAX_HWBP];

 		HWBreakInfo() : tcfBp(NULL), inUse(0) {}

 	};

 

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinProcess.cpp b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinProcess.cpp
index feeae09..8d98d14 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinProcess.cpp
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinProcess.cpp
@@ -192,22 +192,22 @@
 	return hwPageProtMgr.watchpoints.size();

 }

 

-void WinProcess::SetDebugRegister(WinHWBkptMgr::DRMask drMask, ContextAddress addr, WinHWBkptMgr::DRFlags flags) {

+void WinProcess::SetDebugRegister(WinHWBkptMgr::DRNum drNum, const WinHWBkptMgr::DbgRegInfo& info) {

 	const std::list<Context*>& children = GetChildren();

 	std::list<Context*>::const_iterator c;

 	for (c = children.begin(); c != children.end(); c++) {

 		WinThread* winThread = dynamic_cast<WinThread*>(*c);

 		if (winThread != NULL)

-			winThread->SetDebugRegister(drMask, addr, flags);

+			winThread->SetDebugRegister(drNum, info);

 	}

 }

 

-void WinProcess::ClearDebugRegister(WinHWBkptMgr::DRMask drMask) {

+void WinProcess::ClearDebugRegisters(WinHWBkptMgr::DRMask drMask) {

 	const std::list<Context*>& children = GetChildren();

 	std::list<Context*>::const_iterator c;

 	for (c = children.begin(); c != children.end(); c++) {

 		WinThread* winThread = dynamic_cast<WinThread*>(*c);

 		if (winThread != NULL)

-			winThread->ClearDebugRegister(drMask);

+			winThread->ClearDebugRegisters(drMask);

 	}

 }

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinProcess.h b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinProcess.h
index 49423a3..ac0f4a5 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinProcess.h
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinProcess.h
@@ -55,9 +55,9 @@
 	void Initialize();

 

 	friend int WinHWBkptMgr::SetHardwareBreak(TBreakpoint*);

-	void SetDebugRegister(WinHWBkptMgr::DRMask, ContextAddress, WinHWBkptMgr::DRFlags);

+	void SetDebugRegister(WinHWBkptMgr::DRMask, const WinHWBkptMgr::DbgRegInfo&);

 	friend int WinHWBkptMgr::ClearHardwareBreak(TBreakpoint*);

-	void ClearDebugRegister(WinHWBkptMgr::DRMask);

+	void ClearDebugRegisters(WinHWBkptMgr::DRMask);

 

 	bool isRoot_;

 	HANDLE processHandle_;

@@ -67,6 +67,7 @@
 

 	static std::map<int, WinProcess*> processIDMap;

 

+	friend void WinThread::DuplicateDebugRegisters();

 	WinHWBkptMgr		hwBkptMgr;

 

 	friend bool WinThread::HandlePotentialProtctedPage(const DEBUG_EVENT&);

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinThread.cpp b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinThread.cpp
index f4ce51b..fee79ef 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinThread.cpp
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinThread.cpp
@@ -23,6 +23,7 @@
 #include "ProtocolConstants.h"

 #include "RunControlService.h"

 #include "BreakpointsService.h"

+#include "SettingsService.h"

 

 std::map<std::pair<int, int>, WinThread*> WinThread::threadIDMap_;

 

@@ -283,8 +284,8 @@
 

 void WinThread::HandleExecutableEvent(bool isLoaded, const std::string& exePath,

 		unsigned long baseAddress, unsigned long codeSize) {

-	MarkSuspended();

-	EnsureValidContextInfo();

+

+	std::string module = exePath;

 

 	Properties props;

 	if (isLoaded)

@@ -303,12 +304,31 @@
 		assert(!props.empty());

 		props[PROP_MODULE_LOADED] = PropertyValue(false);

 

+		// we don't get the module name for unloaded events, so get it from the properties

+		module = props[PROP_FILE].getStringValue();

+

 		// the executable is unloaded so remove it from our list of executables

 		// otherwise if another executable is later loaded into the same address

 		// and later unloaded, we'll send a bogus unloaded event

 		parentProcess_.GetExecutablesByAddress().erase(baseAddress);

 	}

 

+	if (SettingsService::reportDebugEventForModule(module)) {

+		// report the event.  we'll wait for the debugger to resume the thread

+		// once it's done what it needs to do (set breakpoints, etc)

+		props[PROP_REQUIRED_RESUME] = PropertyValue(true);

+		MarkSuspended();

+		EnsureValidContextInfo();

+	} else {

+		// not in the list of modules we're debugging.  we send the event

+		// so the debugger knows what modules live where, but we're not

+		// debugging it so we don't expect breakpoints to be set.  just

+		// continue the event.  note that sending the event without waiting

+		// for the round trip to get the resume event won't slow us down.

+		props[PROP_REQUIRED_RESUME] = PropertyValue(false);

+		ContinueDebugEvent(parentProcess_.GetOSID(), GetOSID(), DBG_CONTINUE);

+	}

+

 	EventClientNotifier::SendExecutableEvent(this,

 			threadContextInfo_.Eip, props);

 }

@@ -609,27 +629,27 @@
 	}

 }

 

-void WinThread::SetDebugRegister(WinHWBkptMgr::DRMask dRegs, ContextAddress addr, WinHWBkptMgr::DRFlags dr7bits) {

+void WinThread::SetDebugRegister(WinHWBkptMgr::DRNum drNum, const WinHWBkptMgr::DbgRegInfo& info) {

 	bool suspended = isSuspended_;

 	if (!suspended)

 		Suspend();

 	DWORD& DR7 = threadContextInfo_.Dr7;

-	switch (dRegs) {

-	case DR0:

-		threadContextInfo_.Dr0 = addr;

-		DR7 = (DR7 & ~0x000F0003) | (dr7bits<<16) | 0x01;

+	switch (drNum) {

+	case 0:

+		threadContextInfo_.Dr0 = info.address;

+		DR7 = (DR7 & ~0x000F0003) | (info.flags<<16) | 0x01;

 		break;

-	case DR1:

-		threadContextInfo_.Dr1 = addr;

-		DR7 = (DR7 & ~0x00F0000C) | (dr7bits<<20) | 0x04;

+	case 1:

+		threadContextInfo_.Dr1 = info.address;

+		DR7 = (DR7 & ~0x00F0000C) | (info.flags<<20) | 0x04;

 		break;

-	case DR2:

-		threadContextInfo_.Dr2 = addr;

-		DR7 = (DR7 & ~0x0F000030) | (dr7bits<<24) | 0x10;

+	case 2:

+		threadContextInfo_.Dr2 = info.address;

+		DR7 = (DR7 & ~0x0F000030) | (info.flags<<24) | 0x10;

 		break;

-	case DR3:

-		threadContextInfo_.Dr3 = addr;

-		DR7 = (DR7 & ~0xF00000C0) | (dr7bits<<28) | 0x40;

+	case 3:

+		threadContextInfo_.Dr3 = info.address;

+		DR7 = (DR7 & ~0xF00000C0) | (info.flags<<28) | 0x40;

 		break;

 	default:

 		return;

@@ -639,20 +659,38 @@
 		Resume();

 }

 

-void WinThread::ClearDebugRegister(WinHWBkptMgr::DRMask singleDReg) {

+void WinThread::ClearDebugRegisters(WinHWBkptMgr::DRMask mask) {

 	bool suspended = isSuspended_;

 	if (!suspended)

 		Suspend();

 	DWORD& DR7 = threadContextInfo_.Dr7;

-	switch (singleDReg)	{

-	case DR0:		DR7 &= ~0x000F0003;		break;

-	case DR1:		DR7 &= ~0x00F0000C;		break;

-	case DR2:		DR7 &= ~0x0F000030;		break;

-	case DR3:		DR7 &= ~0xF00000C0;		break;

-	default:

-		return;

-	}

+	if (mask & DR0)	DR7 &= ~0x000F0003;

+	if (mask & DR1)	DR7 &= ~0x00F0000C;

+	if (mask & DR2)	DR7 &= ~0x0F000030;

+	if (mask & DR3)	DR7 &= ~0xF00000C0;

+

 	::SetThreadContext(handle_, &threadContextInfo_);

 	if (!suspended)

 		Resume();

 }

+

+void WinThread::DuplicateDebugRegisters() {

+	WinHWBkptMgr& mgr = parentProcess_.hwBkptMgr;

+	if (mgr.inUse

+		&& SUCCEEDED(::GetThreadContext(handle_, &threadContextInfo_))) {

+		int count = 0;

+		for (int i = 0; i < MAX_HWBP && count < MAX_HWBP; ++i) {

+			WinHWBkptMgr::HWBreakInfo& hwbp = mgr.hwBkpt[i];

+			if (hwbp.inUse) {

+				for (int j = 0; j < MAX_HWBP && count < MAX_HWBP; ++j) {

+					WinHWBkptMgr::DRMask drMask = 1 << j;

+					if (hwbp.inUse & drMask) {

+						SetDebugRegister(j, hwbp.dbgReg[j]);

+						++count;

+					}

+				}

+			}

+		}

+		::SetThreadContext(handle_, &threadContextInfo_);

+	}

+}

diff --git a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinThread.h b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinThread.h
index ff96362..c01c18f 100644
--- a/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinThread.h
+++ b/org.eclipse.cdt.debug.edc.windows.agent/src/win_agent/WinThread.h
@@ -12,7 +12,7 @@
 

 #include "stdafx.h"

 #include "ThreadContext.h"

-#include "WinHWBkptMgr.h"	// for DRMask, DRFlags on SetDebugRegister/ClearDebugRegister

+#include "WinHWBkptMgr.h"	// for DRMask, DRFlags on SetDebugRegister/ClearDebugRegisters

 

 #define DR0 0x01

 #define DR1 0x02

@@ -74,8 +74,10 @@
 

 	DWORD GetContinueStatus() const;

 

-	void SetDebugRegister(WinHWBkptMgr::DRMask, ContextAddress, WinHWBkptMgr::DRFlags);

-	void ClearDebugRegister(WinHWBkptMgr::DRMask);

+	void SetDebugRegister(WinHWBkptMgr::DRNum, const WinHWBkptMgr::DbgRegInfo&);

+	void ClearDebugRegisters(WinHWBkptMgr::DRMask);

+

+	void DuplicateDebugRegisters();

 

   private:

 	void Resume();

diff --git a/org.eclipse.cdt.debug.edc.windows/os/win32/x86/EDCWindowsDebugAgent.exe b/org.eclipse.cdt.debug.edc.windows/os/win32/x86/EDCWindowsDebugAgent.exe
index 94c8fca..546f519 100644
--- a/org.eclipse.cdt.debug.edc.windows/os/win32/x86/EDCWindowsDebugAgent.exe
+++ b/org.eclipse.cdt.debug.edc.windows/os/win32/x86/EDCWindowsDebugAgent.exe
Binary files differ
diff --git a/org.eclipse.cdt.debug.edc.windows/src/org/eclipse/cdt/debug/edc/windows/IWindowsAgentSettings.java b/org.eclipse.cdt.debug.edc.windows/src/org/eclipse/cdt/debug/edc/windows/IWindowsAgentSettings.java
new file mode 100644
index 0000000..7bfc833
--- /dev/null
+++ b/org.eclipse.cdt.debug.edc.windows/src/org/eclipse/cdt/debug/edc/windows/IWindowsAgentSettings.java
@@ -0,0 +1,133 @@
+package org.eclipse.cdt.debug.edc.windows;

+

+/**

+ * @since 2.1

+ */

+public interface IWindowsAgentSettings {

+

+	/**

+	 * Allows the client to filter module events (loaded/unloaded).

+	 * 

+	 * By default all module events are reported.  Use this setting if you're

+	 * only interested in events for specific modules.

+	 * 

+	 * Accepts an array of strings containing full paths to the modules

+	 * for which to report events.  Any events for modules not exactly matching

+	 * a path in the module filter list will not be reported to the client.

+	 * 

+	 * The agent maintains a set of modules for its life cycle.  This can be passed

+	 * multiple times if needed.  Each time it will simply append any new modules to

+	 * the list.

+	 */

+	public static final String ADD_MODULES = "addModules";

+

+	/**

+	 * Allows the client to better control the module filter matching.

+	 * 

+	 * The filtering mechanism above requires an exact match of full paths.  If the

+	 * client only requires that the module filename matches, this setting should be

+	 * set to true.  The default value is false.

+	 */

+	public static final String ALLOW_FILENAME_MATCH = "allowFilenameMatch";

+

+	

+	/**

+	 * Allows the client to enable/disable logging of debug string messages.

+	 * 

+	 * Processes under debug can use the Windows API OutputDebugString to print debug

+	 * messages.  When set to true, this setting will send these messages to the client

+	 * through the Logging service.  This is on by default.  Send this setting with a

+	 * value of false to disable.

+	 */

+	public static final String ENABLE_DEBUG_STRING_LOGGING = "enableDebugStringLogging";

+	

+	/**

+	 * Allows the client to control which exceptions should be reported by the agent.

+	 * 

+	 * The bit mask is a 32-bit integer value with each bit representing the enabled

+	 * state of a specific exception.  Set the bit to be notified of the exception.

+	 * Clear the bit to disable notification.

+	 * 

+	 * The constants below can be OR'ed together to form the bit mask to be sent to the agent.

+	 * 

+	 * The list of exceptions and other events is taken from winnt.h and winbase.h and

+	 * documented with the Windows EXCEPTION_RECORD structure here:

+	 * http://msdn.microsoft.com/en-us/library/aa363082%28v=vs.85%29.aspx

+	 * 

+	 * EXCEPTION_BREAKPOINT and EXCEPTION_SINGLE_STEP are intentionally omitted as they're

+	 * required for debug functionality.

+	 * 

+	 * More detail on individual events can be found here:

+	 * http://msdn.microsoft.com/en-us/library/cc704588%28v=prot.10%29.aspx

+	 */

+	public static final String EXCEPTIONS_BITMASK = "exceptionsBitmask";

+	

+	public static final int EXCEPTION_ACCESS_VIOLATION = 1 << 0;

+	

+	public static final int EXCEPTION_ARRAY_BOUNDS_EXCEEDED = 1 << 1;

+

+	public static final int EXCEPTION_DATATYPE_MISALIGNMENT = 1 << 2;

+

+	public static final int EXCEPTION_FLT_DENORMAL_OPERAND = 1 << 3;

+

+	public static final int EXCEPTION_FLT_DIVIDE_BY_ZERO = 1 << 4;

+

+	public static final int EXCEPTION_FLT_INEXACT_RESULT = 1 << 5;

+

+	public static final int EXCEPTION_FLT_INVALID_OPERATION = 1 << 6;

+

+	public static final int EXCEPTION_FLT_OVERFLOW = 1 << 7;

+

+	public static final int EXCEPTION_FLT_STACK_CHECK = 1 << 8;

+

+	public static final int EXCEPTION_FLT_UNDERFLOW = 1 << 9;

+

+	public static final int EXCEPTION_ILLEGAL_INSTRUCTION = 1 << 10;

+

+	public static final int EXCEPTION_IN_PAGE_ERROR = 1 << 11;

+

+	public static final int EXCEPTION_INT_DIVIDE_BY_ZERO = 1 << 12;

+

+	public static final int EXCEPTION_INT_OVERFLOW = 1 << 13;

+

+	public static final int EXCEPTION_INVALID_DISPOSITION = 1 << 14;

+

+	public static final int EXCEPTION_NONCONTINUABLE_EXCEPTION = 1 << 15;

+

+	public static final int EXCEPTION_PRIV_INSTRUCTION = 1 << 16;

+

+	public static final int EXCEPTION_STACK_OVERFLOW = 1 << 17;

+

+	/*

+	 * The following are listed in more recent versions of winbase.h but not well documented.

+	 */

+	public static final int EXCEPTION_GUARD_PAGE = 1 << 18;

+

+	public static final int EXCEPTION_INVALID_HANDLE = 1 << 19;

+

+	/*

+	 * The following are more debug events then exceptions.

+	 */

+	public static final int DBG_CONTROL_C = 1 << 20;

+

+	public static final int DBG_CONTROL_BREAK = 1 << 21;

+

+	/*

+	 * The following are listed in recent versions of winbase.h (but not as exceptions). They can

+	 * be reported by Windows in the same fashion as exceptions though.

+	 */

+	public static final int STATUS_NO_MEMORY = 1 << 22;

+	

+	public static final int STATUS_DLL_INIT_FAILED = 1 << 23;

+

+	/*

+	 * The following are not listed in Windows headers but do get reported in the same fashion

+	 * and the debugger may want to break on them like exceptions.

+	 */

+	public static final int STATUS_DLL_NOT_FOUND = 1 << 24;

+	

+	public static final int STATUS_ENTRYPOINT_NOT_FOUND = 1 << 25;

+

+	public static final int MS_CPLUS_EXCEPTION = 1 << 26;

+

+}