mirror of
https://github.com/mirror/processhacker
synced 2026-06-08 16:03:24 +00:00
8f96d7da1d
git-svn-id: svn://svn.code.sf.net/p/processhacker/code@5060 21ef857c-d57f-4fe0-8362-d861dc6d29cd
120 lines
4.5 KiB
Diff
120 lines
4.5 KiB
Diff
Index: plugins/DotNetTools/stackext.c
|
|
===================================================================
|
|
--- plugins/DotNetTools/stackext.c (revision 5058)
|
|
+++ plugins/DotNetTools/stackext.c (working copy)
|
|
@@ -48,16 +48,29 @@
|
|
{
|
|
PTHREAD_STACK_CONTEXT context;
|
|
BOOLEAN isDotNet;
|
|
+ HANDLE processHandle;
|
|
+ BOOLEAN isWow64 = FALSE;
|
|
|
|
if (!NT_SUCCESS(PhGetProcessIsDotNet(Control->u.Initializing.ProcessId, &isDotNet)) || !isDotNet)
|
|
return;
|
|
|
|
+ if (NT_SUCCESS(PhOpenProcess(&processHandle, ProcessQueryAccess, Control->u.Initializing.ProcessId)))
|
|
+ {
|
|
+ PhGetProcessIsWow64(processHandle, &isWow64);
|
|
+ NtClose(processHandle);
|
|
+ }
|
|
+
|
|
+ if (isWow64)
|
|
+ return;
|
|
+
|
|
context = PhAllocate(sizeof(THREAD_STACK_CONTEXT));
|
|
context->Support = CreateClrProcessSupport(Control->u.Initializing.ProcessId);
|
|
|
|
PhAcquireQueuedLockExclusive(&ContextHashtableLock);
|
|
PhAddItemSimpleHashtable(ContextHashtable, Control->UniqueKey, context);
|
|
PhReleaseQueuedLockExclusive(&ContextHashtableLock);
|
|
+
|
|
+ Control->u.Initializing.CustomWalk = TRUE;
|
|
}
|
|
break;
|
|
case PluginThreadStackUninitializing:
|
|
@@ -133,5 +146,84 @@
|
|
}
|
|
}
|
|
break;
|
|
+ case PluginThreadStackWalkStack:
|
|
+ {
|
|
+ PTHREAD_STACK_CONTEXT context;
|
|
+ PVOID *item;
|
|
+ IXCLRDataTask *task;
|
|
+
|
|
+ PhAcquireQueuedLockExclusive(&ContextHashtableLock);
|
|
+
|
|
+ item = PhFindItemSimpleHashtable(ContextHashtable, Control->UniqueKey);
|
|
+
|
|
+ if (item)
|
|
+ context = *item;
|
|
+ else
|
|
+ context = NULL;
|
|
+
|
|
+ PhReleaseQueuedLockExclusive(&ContextHashtableLock);
|
|
+
|
|
+ if (!context)
|
|
+ return;
|
|
+
|
|
+ if (SUCCEEDED(IXCLRDataProcess_GetTaskByOSThreadID(
|
|
+ context->Support->DataProcess,
|
|
+ (ULONG)Control->u.WalkStack.ClientId->UniqueThread,
|
|
+ &task
|
|
+ )))
|
|
+ {
|
|
+ IXCLRDataStackWalk *stackWalk;
|
|
+
|
|
+ if (SUCCEEDED(IXCLRDataTask_CreateStackWalk(task, 0xf, &stackWalk)))
|
|
+ {
|
|
+ HRESULT result;
|
|
+ BOOLEAN firstTime = TRUE;
|
|
+ CONTEXT context;
|
|
+ ULONG contextSize;
|
|
+
|
|
+ context.ContextFlags = CONTEXT_ALL;
|
|
+ PhGetThreadContext(Control->u.WalkStack.ThreadHandle, &context);
|
|
+ result = IXCLRDataStackWalk_SetContext2(stackWalk, CLRDATA_STACK_SET_CURRENT_CONTEXT, sizeof(CONTEXT), (BYTE *)&context);
|
|
+
|
|
+ while (SUCCEEDED(result = IXCLRDataStackWalk_Next(stackWalk)) && result != S_FALSE)
|
|
+ {
|
|
+ if (firstTime)
|
|
+ {
|
|
+ PhWalkThreadStack(
|
|
+ Control->u.WalkStack.ThreadHandle,
|
|
+ Control->u.WalkStack.ProcessHandle,
|
|
+ Control->u.WalkStack.ClientId,
|
|
+ PH_WALK_KERNEL_STACK,
|
|
+ Control->u.WalkStack.Callback,
|
|
+ Control->u.WalkStack.CallbackContext
|
|
+ );
|
|
+
|
|
+ Control->u.WalkStack.Status = STATUS_SUCCESS; // prevent default walk
|
|
+ firstTime = FALSE;
|
|
+ }
|
|
+
|
|
+ if (SUCCEEDED(IXCLRDataStackWalk_GetContext(stackWalk, CONTEXT_CONTROL, sizeof(context), &contextSize, (BYTE *)&context)))
|
|
+ {
|
|
+ PH_THREAD_STACK_FRAME stackFrame;
|
|
+
|
|
+ memset(&stackFrame, 0, sizeof(PH_THREAD_STACK_FRAME));
|
|
+
|
|
+#ifdef _M_X64
|
|
+ stackFrame.PcAddress = (PVOID)context.Rip;
|
|
+#else
|
|
+ stackFrame.PcAddress = (PVOID)context.Eip;
|
|
+#endif
|
|
+
|
|
+ Control->u.WalkStack.Callback(&stackFrame, Control->u.WalkStack.CallbackContext);
|
|
+ }
|
|
+ }
|
|
+
|
|
+ IXCLRDataStackWalk_Release(stackWalk);
|
|
+ }
|
|
+
|
|
+ IXCLRDataTask_Release(task);
|
|
+ }
|
|
+ }
|
|
+ break;
|
|
}
|
|
}
|