public UnifiedStackFrame ConvertToUnified(ClrStackFrame frame, SourceLocation sourceLocation, ThreadInfo info) { var result = new UnifiedStackFrame(frame, sourceLocation); result.ThreadContext = info.ContextStruct; return result; }
/* WaitForSingleObject * * 1st: RCX (handle) * 000007fe`fd24102b 488bf9 mov rdi,rcx * 2nd - RDX (Timeout) * 000007fe`fd241029 8bf2 mov esi,edx */ /* EnterCriticalSection * * 1st: RCX (CRITICAL_SECTION ptr) * 00007ffd`b57310cb 488bf9 mov rdi,rcx */ internal override Params GetWaitForMultipleObjectsParams(UnifiedStackFrame frame) { Params result = new Params(); //RCX, RDX, R8, and R9 //RCX //00007ffd`b57312e5 8bd9 mov ebx,ecx var handlesCount = frame.ThreadContext.Context_amd64.Rbx; if (handlesCount > Kernel32.Const.MAXIMUM_WAIT_OBJECTS) { throw new ArgumentOutOfRangeException($"Cannot await for more then : {Kernel32.Const.MAXIMUM_WAIT_OBJECTS}, given value :{handlesCount}"); } result.First = handlesCount; //RDX //00007ffd`b57312e2 4c8bea mov r13,rdx var hArrayPtr = frame.ThreadContext.Context_amd64.R13; result.Second = hArrayPtr; //3rd - R8: WaitAll (BOOLEAN) //00007ffd`b57312ca 4489442418 mov dword ptr[rsp + 18h],r8d var rspPtr = frame.StackPointer + 24; result.Third = base.ReadBoolean(rspPtr); //R9 ////00007ffd`b57312df 458bf1 mov r14d,r9d var waitTime = frame.ThreadContext.Context_amd64.R14; result.Fourth = waitTime; return result; }
/* WaitForSingleObject * * 1st: RCX (handle) * 000007fe`fd24102b 488bf9 mov rdi,rcx * 2nd - RDX (Timeout) * 000007fe`fd241029 8bf2 mov esi,edx */ /* EnterCriticalSection * * 1st: RCX (CRITICAL_SECTION ptr) * 00007ffd`b57310cb 488bf9 mov rdi,rcx */ internal override Params GetWaitForMultipleObjectsParams(UnifiedStackFrame frame) { Params result = new Params(); //1st: RCX (Wait Objects count) //00007ffd`b57312e5 8bd9 mov ebx,ecx result.First = frame.ThreadContext.Context_amd64.Rbx; if (result.First > Kernel32.Const.MAXIMUM_WAIT_OBJECTS) { throw new ArgumentOutOfRangeException($"Cannot await for more then : {Kernel32.Const.MAXIMUM_WAIT_OBJECTS}, given value { result.First}"); } //2nd - RDX (Array ptr) //00007ffd`b57312e2 4c8bea mov r13,rdx result.Second = frame.ThreadContext.Context_amd64.R13; //3rd - R8: WaitAll (BOOLEAN) //00007ffa`d7653a90 4489442444 mov dword ptr [rsp+44h],r8d var rspPtr = frame.StackPointer + 68; result.Third = base.ReadBoolean(rspPtr); //4th - R9: Timeout (DWORD) //00007ffa`d7653a8d 458be1 mov r12d,r9d var waitTime = frame.ThreadContext.Context_amd64.R12; result.Fourth = waitTime; return result; }
internal bool CheckForWinApiCalls(UnifiedStackFrame frame, string key) { bool result = frame != null && !String.IsNullOrEmpty(frame.Method) && frame.Method != null && frame.Method.Contains(key); return result; }
internal virtual Params GetWaitForSingleObjectParams(UnifiedStackFrame frame) { Params result = new Params(); result.First = frame.ThreadContext.Context_amd64.Rdi; result.Second = frame.ThreadContext.Context_amd64.Rsi; return result; }
internal bool GetCriticalSectionBlockingObject(UnifiedStackFrame frame, ClrRuntime runtime, out UnifiedBlockingObject blockingObject) { bool result = false; if (frame.Handles != null && frame.Method.Contains(ENTER_CRITICAL_SECTION_FUNCTION_NAME)) { blockingObject = GetCriticalSectionBlockingObject(frame, runtime); result = blockingObject != null; } else { blockingObject = null; } return result; }
/* WaitForSingleObject * * 1st: RCX (handle) * 000007fe`fd24102b 488bf9 mov rdi,rcx * 2nd - RDX (Timeout) * 000007fe`fd241029 8bf2 mov esi,edx */ /* EnterCriticalSection * * 1st: RCX (CRITICAL_SECTION ptr) * 00007ffd`b57310cb 488bf9 mov rdi,rcx */ internal override Params GetWaitForMultipleObjectsParams(UnifiedStackFrame frame) { throw new NotImplementedException(); Params result = new Params(); //1st: RCX (Wait Objects count) //000007fe`fd24155a 48894c2408 mov qword ptr [rsp+8],rcx var rspPtr = frame.StackPointer + 8; result.Third = base.ReadULong(rspPtr); //2nd - RDX (Array ptr) //3rd - R8: WaitAll (BOOLEAN) //4th - R9: Timeout (DWORD) return result; }
internal List<UnifiedStackFrame> ConvertToUnified(IEnumerable<DEBUG_STACK_FRAME> stackFrames, ClrRuntime runtime, IDebugClient debugClient, ThreadInfo info, uint pid = Constants.INVALID_PID) { bool waitFound = false; var reversed = stackFrames.Reverse(); List<UnifiedStackFrame> stackTrace = new List<UnifiedStackFrame>(); foreach (var frame in reversed) { var unified_frame = new UnifiedStackFrame(frame, (IDebugSymbols2)debugClient); unified_frame.ThreadContext = info.ContextStruct; if (!waitFound) { waitFound = Inpsect(unified_frame, runtime, pid); } stackTrace.Add(unified_frame); } return stackTrace; }
/// <summary> /// Original Function call example: /// DWORD WINAPI WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds); /// </summary> protected override void DealWithSingle(UnifiedStackFrame frame, ClrRuntime runtime, uint pid) { var paramz = Strategy.GetWaitForSingleObjectParams(frame); EnrichUnifiedStackFrame(frame, paramz.First, pid); }
/// <summary> /// Original Function call example: /// DWORD WaitForMultipleObjects(DWORD nCount,HANDLE* lpHandles,BOOL bWaitAll,DWORD dwMilliseconds); /// </summary> protected override void DealWithMultiple(UnifiedStackFrame frame, ClrRuntime runtime, uint pid) { var paramz = Strategy.GetWaitForMultipleObjectsParams(frame); EnrichUnifiedStackFrame(frame, runtime, pid, paramz.First, paramz.Second); }
/// <summary> /// Original Function call example: /// void WINAPI EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection); /// </summary> protected override void DealWithCriticalSection(UnifiedStackFrame frame, ClrRuntime runtime, uint pid) { var paramz = Strategy.GetEnterCriticalSectionParam(frame); EnrichUnifiedStackFrame(frame, paramz.First, pid); }
protected void EnrichUnifiedStackFrame(UnifiedStackFrame frame, ulong handle, uint pid) { UnifiedHandle unifiedHandle = GenerateUnifiedHandle(handle, pid); if (unifiedHandle != null) { frame.Handles = new List<UnifiedHandle>(); frame.Handles.Add(unifiedHandle); } }
internal virtual Params GetEnterCriticalSectionParam(UnifiedStackFrame frame) { Params result = new Params(); result.First = frame.ThreadContext.Context_amd64.Rdi; return result; }
protected bool Inpsect(UnifiedStackFrame frame, ClrRuntime runtime, uint pid) { bool waitCallFound = false; if (CheckForWinApiCalls(frame, WAIT_FOR_SINGLE_OBJECTS_FUNCTION_NAME)) { DealWithSingle(frame, runtime, pid); } else if (waitCallFound = CheckForWinApiCalls(frame, WAIT_FOR_MULTIPLE_OBJECTS_FUNCTION_NAME)) { DealWithMultiple(frame, runtime, pid); } else if(CheckForWinApiCalls(frame, ENTER_CRITICAL_SECTION_FUNCTION_NAME)) { DealWithCriticalSection(frame, runtime, pid); } return waitCallFound; }
protected abstract UnifiedBlockingObject GetCriticalSectionBlockingObject(UnifiedStackFrame frame, ClrRuntime runtime);
protected void EnrichUnifiedStackFrame(UnifiedStackFrame frame, ClrRuntime runtime, uint pid, ulong waitCount, ulong hPtr) { if (waitCount > Kernel32.Const.MAXIMUM_WAIT_OBJECTS) { throw new InvalidOperationException($"waitCount exceeded MAXIMUM_WAIT_OBJECTS :{ waitCount }"); } var handles = ReadFromMemmory(hPtr, (uint)waitCount, runtime); frame.Handles = new List<UnifiedHandle>(); foreach (var handle in handles) { ulong handleUint = Convert(handle); UnifiedHandle unifiedHandle = GenerateUnifiedHandle(handleUint, pid); if (unifiedHandle != null) { frame.Handles.Add(unifiedHandle); } } }
/// <summary> /// Original Function call example: /// void WINAPI EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection); /// </summary> protected override UnifiedBlockingObject GetCriticalSectionBlockingObject(UnifiedStackFrame frame, ClrRuntime runtime) { UnifiedBlockingObject result = null; var paramz = Strategy.GetEnterCriticalSectionParam(frame); result = new UnifiedBlockingObject(paramz.First, UnifiedBlockingType.CriticalSectionObject); return result; }
protected abstract void DealWithSingle(UnifiedStackFrame frame, ClrRuntime runtime, uint pid);
protected abstract void DealWithCriticalSection(UnifiedStackFrame frame, ClrRuntime runtime, uint pid);
internal abstract Params GetWaitForMultipleObjectsParams(UnifiedStackFrame frame);