diff options
author | Andrew Au <andrewau@microsoft.com> | 2017-06-15 21:07:48 +0300 |
---|---|---|
committer | Andrew Au <andrewau@microsoft.com> | 2017-06-15 21:07:48 +0300 |
commit | 34b00937c6c83185d3f3512df2b71d777263f3b4 (patch) | |
tree | 5e4c9b86627266158e0c9bc66afb934f1c3bcd99 | |
parent | 3805f6558511e79f9367723147f1aeff1be4cc20 (diff) |
Debugger Support
[tfs-changeset: 1661846]
-rw-r--r-- | src/Native/Runtime/Debug.h | 9 | ||||
-rw-r--r-- | src/Native/Runtime/DebuggerHook.cpp | 64 | ||||
-rw-r--r-- | src/Native/Runtime/DebuggerHook.h | 13 | ||||
-rw-r--r-- | src/Native/Runtime/gcrhenv.cpp | 5 | ||||
-rw-r--r-- | src/Native/Runtime/gcrhinterface.h | 3 | ||||
-rw-r--r-- | src/Native/Runtime/gcrhscan.cpp | 2 |
6 files changed, 70 insertions, 26 deletions
diff --git a/src/Native/Runtime/Debug.h b/src/Native/Runtime/Debug.h index 685298504..48156fc19 100644 --- a/src/Native/Runtime/Debug.h +++ b/src/Native/Runtime/Debug.h @@ -14,7 +14,8 @@ enum DebuggerGcProtectionRequestKind : uint16_t { EnsureConservativeReporting = 1, RemoveConservativeReporting = 2, - RemoveHandle = 3 + EnsureHandle = 3, + RemoveHandle = 4 }; struct GcProtectionMessage @@ -27,7 +28,11 @@ struct GcProtectionMessage struct GcProtectionRequest { DebuggerGcProtectionRequestKind kind; - uint16_t size; + union + { + uint16_t size; + uint16_t type; + }; uint32_t identifier; uint64_t address; }; diff --git a/src/Native/Runtime/DebuggerHook.cpp b/src/Native/Runtime/DebuggerHook.cpp index dafa56b4b..5c0708c41 100644 --- a/src/Native/Runtime/DebuggerHook.cpp +++ b/src/Native/Runtime/DebuggerHook.cpp @@ -10,14 +10,13 @@ #include "DebuggerHook.h" #include "DebugEventSource.h" - GVAL_IMPL_INIT(UInt32, g_numGcProtectionRequests, 0); #ifndef DACCESS_COMPILE -/* static */ DebuggerProtectedBufferList* DebuggerHook::s_debuggerProtectedBuffers = nullptr; +/* static */ DebuggerProtectedBufferListNode* DebuggerHook::s_debuggerProtectedBuffers = nullptr; -/* static */ DebuggerOwnedHandleList* DebuggerHook::s_debuggerOwnedHandleList = nullptr; +/* static */ DebuggerOwnedHandleListNode* DebuggerHook::s_debuggerOwnedHandles = nullptr; /* static */ UInt32 DebuggerHook::s_debuggeeInitiatedHandleIdentifier = 2; @@ -67,6 +66,10 @@ GVAL_IMPL_INIT(UInt32, g_numGcProtectionRequests, 0); { RemoveConservativeReporting(requests + i); } + else if (requests[i].kind == DebuggerGcProtectionRequestKind::EnsureHandle) + { + EnsureHandle(requests + i); + } else if (requests[i].kind == DebuggerGcProtectionRequestKind::RemoveHandle) { RemoveHandle(requests + i); @@ -79,7 +82,7 @@ GVAL_IMPL_INIT(UInt32, g_numGcProtectionRequests, 0); /* static */ UInt32 DebuggerHook::RecordDebuggeeInitiatedHandle(void* objectHandle) { - DebuggerOwnedHandleList* head = new (nothrow) DebuggerOwnedHandleList(); + DebuggerOwnedHandleListNode* head = new (nothrow) DebuggerOwnedHandleListNode(); if (head == nullptr) { return 0; @@ -87,8 +90,8 @@ GVAL_IMPL_INIT(UInt32, g_numGcProtectionRequests, 0); head->handle = objectHandle; head->identifier = DebuggerHook::s_debuggeeInitiatedHandleIdentifier; - head->next = s_debuggerOwnedHandleList; - s_debuggerOwnedHandleList = head; + head->next = s_debuggerOwnedHandles; + s_debuggerOwnedHandles = head; s_debuggeeInitiatedHandleIdentifier += 2; @@ -97,10 +100,11 @@ GVAL_IMPL_INIT(UInt32, g_numGcProtectionRequests, 0); /* static */ void DebuggerHook::EnsureConservativeReporting(GcProtectionRequest* request) { - DebuggerProtectedBufferList* tail = DebuggerHook::s_debuggerProtectedBuffers; - s_debuggerProtectedBuffers = new (std::nothrow) DebuggerProtectedBufferList(); + DebuggerProtectedBufferListNode* tail = DebuggerHook::s_debuggerProtectedBuffers; + s_debuggerProtectedBuffers = new (std::nothrow) DebuggerProtectedBufferListNode(); if (s_debuggerProtectedBuffers == nullptr) { + s_debuggerProtectedBuffers = tail; // TODO, FuncEval, we cannot handle the debugger request to protect a buffer (we have to break our promise) // TODO, FuncEval, we need to figure out how to communicate this broken promise to the debugger } @@ -115,8 +119,8 @@ GVAL_IMPL_INIT(UInt32, g_numGcProtectionRequests, 0); /* static */ void DebuggerHook::RemoveConservativeReporting(GcProtectionRequest* request) { - DebuggerProtectedBufferList* prev = nullptr; - DebuggerProtectedBufferList* curr = DebuggerHook::s_debuggerProtectedBuffers; + DebuggerProtectedBufferListNode* prev = nullptr; + DebuggerProtectedBufferListNode* curr = DebuggerHook::s_debuggerProtectedBuffers; while (true) { if (curr == nullptr) @@ -126,7 +130,7 @@ GVAL_IMPL_INIT(UInt32, g_numGcProtectionRequests, 0); } if (curr->identifier == request->identifier) { - DebuggerProtectedBufferList* toDelete = curr; + DebuggerProtectedBufferListNode* toDelete = curr; if (prev == nullptr) { // We are trying to remove the head of the linked list @@ -148,10 +152,38 @@ GVAL_IMPL_INIT(UInt32, g_numGcProtectionRequests, 0); } } +/* static */ void DebuggerHook::EnsureHandle(GcProtectionRequest* request) +{ + DebuggerOwnedHandleListNode* tail = DebuggerHook::s_debuggerOwnedHandles; + s_debuggerOwnedHandles = new (std::nothrow) DebuggerOwnedHandleListNode(); + if (s_debuggerOwnedHandles == nullptr) + { + s_debuggerOwnedHandles = tail; + // TODO, FuncEval, we cannot handle the debugger request to protect a buffer (we have to break our promise) + // TODO, FuncEval, we need to figure out how to communicate this broken promise to the debugger + } + else + { + int handleType; + switch (request->type) + { + case 1: handleType = 2 /* == HNDTYPE_STRONG */; break; + case 2: handleType = 1 /* == HNDTYPE_WEAK_LONG */; break; + default: + assert("Debugger is passing in a wrong handle type" && false); + handleType = 2 /* == HNDTYPE_STRONG */; + } + void* handle = RedhawkGCInterface::CreateTypedHandle((void*)request->address, handleType); + s_debuggerOwnedHandles->handle = handle; + s_debuggerOwnedHandles->identifier = request->identifier; + s_debuggerOwnedHandles->next = tail; + } +} + /* static */ void DebuggerHook::RemoveHandle(GcProtectionRequest* request) { - DebuggerOwnedHandleList* prev = nullptr; - DebuggerOwnedHandleList* curr = DebuggerHook::s_debuggerOwnedHandleList; + DebuggerOwnedHandleListNode* prev = nullptr; + DebuggerOwnedHandleListNode* curr = DebuggerHook::s_debuggerOwnedHandles; while (true) { if (curr == nullptr) @@ -161,13 +193,13 @@ GVAL_IMPL_INIT(UInt32, g_numGcProtectionRequests, 0); } if (curr->identifier == request->identifier) { - DebuggerOwnedHandleList* toDelete = curr; + DebuggerOwnedHandleListNode* toDelete = curr; RedhawkGCInterface::DestroyTypedHandle(toDelete->handle); if (prev == nullptr) { // We are trying to remove the head of the linked list - DebuggerHook::s_debuggerOwnedHandleList = curr->next; + DebuggerHook::s_debuggerOwnedHandles = curr->next; } else { @@ -192,7 +224,7 @@ EXTERN_C REDHAWK_API UInt32 __cdecl RhpRecordDebuggeeInitiatedHandle(void* objec EXTERN_C REDHAWK_API void __cdecl RhpVerifyDebuggerCleanup() { - assert(DebuggerHook::s_debuggerOwnedHandleList == nullptr); + assert(DebuggerHook::s_debuggerOwnedHandles == nullptr); assert(DebuggerHook::s_debuggerProtectedBuffers == nullptr); } diff --git a/src/Native/Runtime/DebuggerHook.h b/src/Native/Runtime/DebuggerHook.h index c64ff8b0c..3f050a4d0 100644 --- a/src/Native/Runtime/DebuggerHook.h +++ b/src/Native/Runtime/DebuggerHook.h @@ -18,19 +18,19 @@ #ifndef DACCESS_COMPILE -struct DebuggerProtectedBufferList +struct DebuggerProtectedBufferListNode { UInt64 address; UInt16 size; UInt32 identifier; - struct DebuggerProtectedBufferList* next; + struct DebuggerProtectedBufferListNode* next; }; -struct DebuggerOwnedHandleList +struct DebuggerOwnedHandleListNode { void* handle; UInt32 identifier; - struct DebuggerOwnedHandleList* next; + struct DebuggerOwnedHandleListNode* next; }; class DebuggerHook @@ -38,11 +38,12 @@ class DebuggerHook public: static void OnBeforeGcCollection(); static UInt32 RecordDebuggeeInitiatedHandle(void* handle); - static DebuggerProtectedBufferList* s_debuggerProtectedBuffers; - static DebuggerOwnedHandleList* s_debuggerOwnedHandleList; + static DebuggerProtectedBufferListNode* s_debuggerProtectedBuffers; + static DebuggerOwnedHandleListNode* s_debuggerOwnedHandles; private: static void EnsureConservativeReporting(GcProtectionRequest* request); static void RemoveConservativeReporting(GcProtectionRequest* request); + static void EnsureHandle(GcProtectionRequest* request); static void RemoveHandle(GcProtectionRequest* request); static UInt32 s_debuggeeInitiatedHandleIdentifier; }; diff --git a/src/Native/Runtime/gcrhenv.cpp b/src/Native/Runtime/gcrhenv.cpp index 93476f8dc..30ac3210c 100644 --- a/src/Native/Runtime/gcrhenv.cpp +++ b/src/Native/Runtime/gcrhenv.cpp @@ -894,6 +894,11 @@ void RedhawkGCInterface::DestroyTypedHandle(void * handle) ::DestroyTypedHandle((OBJECTHANDLE)handle); } +void* RedhawkGCInterface::CreateTypedHandle(void* pObject, int type) +{ + return (void*)::CreateTypedHandle(g_HandleTableMap.pBuckets[0]->pTable[GetCurrentThreadHomeHeapNumber()], (Object*)pObject, type); +} + void GCToEEInterface::SuspendEE(SUSPEND_REASON reason) { #ifdef FEATURE_EVENT_TRACE diff --git a/src/Native/Runtime/gcrhinterface.h b/src/Native/Runtime/gcrhinterface.h index dfcd00939..2cea66073 100644 --- a/src/Native/Runtime/gcrhinterface.h +++ b/src/Native/Runtime/gcrhinterface.h @@ -158,7 +158,8 @@ public: static void SetLastAllocEEType(EEType *pEEType); // Used by debugger hook - static void DestroyTypedHandle(void * handle); + static void* CreateTypedHandle(void* object, int type); + static void DestroyTypedHandle(void* handle); private: // The EEType for the last allocation. This value is used inside of the GC allocator diff --git a/src/Native/Runtime/gcrhscan.cpp b/src/Native/Runtime/gcrhscan.cpp index 31ac4d7a5..e342e2c78 100644 --- a/src/Native/Runtime/gcrhscan.cpp +++ b/src/Native/Runtime/gcrhscan.cpp @@ -49,7 +49,7 @@ void EnumAllStaticGCRefs(EnumGcRefCallbackFunc * fn, EnumGcRefScanContext * sc) void GCToEEInterface::GcScanRoots(EnumGcRefCallbackFunc * fn, int condemned, int max_gen, EnumGcRefScanContext * sc) { - DebuggerProtectedBufferList* cursor = DebuggerHook::s_debuggerProtectedBuffers; + DebuggerProtectedBufferListNode* cursor = DebuggerHook::s_debuggerProtectedBuffers; while (cursor != nullptr) { GcEnumObjectsConservatively((PTR_PTR_Object)cursor->address, (PTR_PTR_Object)(cursor->address + cursor->size), fn, sc); |