WinDbg: Problems attaching to process

Sometimes various problems prevent WinDbg from attaching to a process.

I experienced some recently, that I have described here.

 

Trying to attach 32-bit WinDbg (x86) to a 64-bit process

WinDbg_Could_not_attach_to_process_NTSTATUS_0xC00000BB

Could not attach to process 11576, NTSTATUS 0xC00000BB

The request is not supported.

 

If you get this error message, please check if the process is 32-bit or 64-bit.

Then try attaching again with the right version of WinDbg.

 

Attaching 64-bit WinDbg (x64) to a 32-bit process

Attaching 64-bit WinDbg (x64) to a 32-bit process is possible, but it’s usually not very useful. That’s because it shows a WOW64 view of the process, which limits the debugging options.

 

Trying to attach to process with insufficient user permissions

WinDbg_Could_not_attach_to_process_error_0n5

Could not attach to process 4160, Win32 error 0n5

Access is denied.

 

This error may occur if WinDbg has insufficient permissions.

Try running WinDbg “As Administrator” and try attaching to the process again.

 

Trying to attach to process when it is already being debugged

WinDbg_Could_not_attach_to_process_NTSTATUS_0xC0000048

Could not attach to process 6128, NTSTATUS 0xC0000048

An attempt to set a process's DebugPort or ExceptionPort was made, but a port already exists in the process or an attempt to set a file's CompletionPort made, but a port was already set in the file or an attempt to set an ALPC port's associated completion port was made, but it is already set.

 

This problem usually occurs if the process is already being debugged. The other debugger could be Visual Studio, ProcDump or another tool.

Check if other debuggers are attached, detach them and then try attaching to the process again with WinDbg.

Debugging Reporting Services with WinDbg

I recently needed to use classes and methods from MSXML6.dll in Reporting Services reports (to make web service calls).

Tried to instantiate XMLHTTP and DOMDocument from MSXML6.dll with late binding like this:

Request = CreateObject("MSXML2.XMLHTTP.6.0")
Doc = CreateObject("MSXML2.DOMDocument.6.0")

However it failed with a SecurityException, but the exact cause was unknown.

 

I decided to identify the cause by attaching WinDbg (x86) to RsReportHost.exe

 

On each report refresh I noticed a number of exceptions like:

(2a54.34d4): CLR exception - code e0434352 (first chance)
(2a54.34d4): CLR exception - code e0434352 (first chance)
(2a54.34d4): C++ EH exception - code e06d7363 (first chance)
(2a54.34d4): C++ EH exception - code e06d7363 (first chance)

 

I configured WinDbg to break on first chance exceptions under: Debug -> Event Filters…

Debug_Event_Filters

 

And loaded the SOS extension with:

.loadby sos clr

 

Typical (top part) of the call stack was:

0:007> !clrstack
OS Thread Id: 0x55f4 (7)
Child SP       IP Call Site
00bbb28c 7652dae8 [HelperMethodFrame: 00bbb28c]
00bbb33c 72f25d5a System.Security.CodeAccessSecurityEngine.ThrowSecurityException(...)
00bbb36c 72f25cad System.Security.CodeAccessSecurityEngine.ThrowSecurityException(...)
00bbb394 72f2136c System.Security.CodeAccessSecurityEngine.CheckSetHelper(...)
00bbb3e4 73581acf System.Security.CodeAccessSecurityEngine.CheckSetHelper(...)
00bbb50c 73e41376 [GCFrame: 00bbb50c]
00bbbd08 73e41376 [GCFrame: 00bbbd08]
00bbbdc0 73e41376 [GCFrame: 00bbbdc0]
00bbbf58 73e41376 [DebuggerSecurityCodeMarkFrame: 00bbbf58]
00bbbee4 73e41376 [HelperMethodFrame: 00bbbee4]
00bbbf7c 09a16859 Microsoft.VisualBasic.Interaction.CreateObject(System.String, System.String)
00bbbfa4 09a180ba ReportExprHostImpl+CustomCodeProxy.CallServiceTest2()
00bbbfcc 09a1807b ReportExprHostImpl+Description_TextBoxExprHost+Paragraph00_ParagraphExprHost+TextRun00_TextRunExprHost.get_ValueExpr()

(parameters trimmed for readability)

 

I checked the mscorlib.dll code for System.Security.CodeAccessSecurityEngine.CheckSetHelper(…) in ILSpy.

Noticed something interesting: The local variable permThatFailed could show which permission was missing.

This was also used when calling System.Security.SecurityException.MakeSecurityException, so that was an ideal place to set a breakpoint.

 

Set a breakpoint with !bpmd:

0:015> !bpmd mscorlib.dll System.Security.SecurityException.MakeSecurityException
Found 1 methods in module 72bf1000...
MethodDesc = 72c88e84
Setting breakpoint: bp 72F33813 [System.Security.SecurityException.MakeSecurityException(System.Reflection.AssemblyName, System.Security.Policy.Evidence, System.Security.PermissionSet, System.Security.PermissionSet, System.RuntimeMethodHandleInternal, System.Security.Permissions.SecurityAction, System.Object, System.Security.IPermission)]
Adding pending breakpoints...

 

Continued execution, refreshed the report and then checked the call stack with parameters:

0:014> !clrstack -p
OS Thread Id: 0x54c0 (14)
Child SP       IP Call Site
0103bd88 72f33813 System.Security.SecurityException.MakeSecurityException(System.Reflection.AssemblyName, System.Security.Policy.Evidence, System.Security.PermissionSet, System.Security.PermissionSet, System.RuntimeMethodHandleInternal, System.Security.Permissions.SecurityAction, System.Object, System.Security.IPermission)
PARAMETERS:
asmName (<CLR reg>) = 0x036c4bd0
asmEvidence (<CLR reg>) = 0x036c5b64
granted (0x0103bda0) = 0x00000000
refused (0x0103bd9c) = 0x036c4bd0
rmh (0x0103bd98) = 0x036c5b64
action (0x0103bd94) = 0x00000000
demand (0x0103bd90) = 0x00000000
permThatFailed (0x0103bd8c) = 0x00000002

 

The permThatFailed parameter consistently had the value 2.

I looked up the values for the SecurityPermissionFlag enumeration in ILSpy:

And found this:

/// <summary>Ability to call unmanaged code.</summary>
UnmanagedCode = 2,

 

Conclusion

The SecurityException occured because permission to execute unmanaged code was missing.

Get .NET call stack when files are written with WinDbg

I was interested in learning how Neuron ESB performed logging internally.

(To see if it would be relevant to use the same classes and methods for logging in custom C# process steps and possibly other situations)

 

At first I used Process Monitor.

I found a WriteFile event, where a log file was updated.

Neuron_ESB_WriteFile_Process_Monitor_Event

I checked the stack under event properties.

Neuron_ESB_WriteFile_Process_Monitor_Event_Properties_Stack

The native stack trace didn’t tell me which .NET classes or methods that were in use, but it did give me an idea:

Perhaps I could use WinDbg to get the .NET call stack for each call to WriteFile in kernel32.dll

 

Indeed this was possible by:

1. Starting WinDbg (x64) as Administrator.

2. Attaching to the ESBService.exe process.

3. Loading the SOS extension with:

.loadby sos clr

4. Setting a breakpoint with a command to show the .NET call stack and continue execution with:

bp kernel32!WriteFile "!clrstack; g"

5. Continuing execution with:

g

 

This showed the .NET call stack every time files were written.

Most WriteFile calls were for logging (as expected).

An example:

OS Thread Id: 0x2354 (35)
Child SP               IP Call Site
000000001836e028 00000000775a1fa0 [InlinedCallFrame: 000000001836e028] Microsoft.Win32.Win32Native.WriteFile(Microsoft.Win32.SafeHandles.SafeFileHandle, Byte*, Int32, Int32 ByRef, IntPtr)
000000001836e028 000007feea284cf4 [InlinedCallFrame: 000000001836e028] Microsoft.Win32.Win32Native.WriteFile(Microsoft.Win32.SafeHandles.SafeFileHandle, Byte*, Int32, Int32 ByRef, IntPtr)
000000001836dff0 000007feea284cf4 DomainNeutralILStubClass.IL_STUB_PInvoke(Microsoft.Win32.SafeHandles.SafeFileHandle, Byte*, Int32, Int32 ByRef, IntPtr)
000000001836e0d0 000007feea265984 System.IO.FileStream.WriteFileNative(Microsoft.Win32.SafeHandles.SafeFileHandle, Byte[], Int32, Int32, System.Threading.NativeOverlapped*, Int32 ByRef)
000000001836e130 000007feea2658d2 System.IO.FileStream.WriteCore(Byte[], Int32, Int32)
000000001836e1a0 000007feea265847 System.IO.FileStream.FlushInternalBuffer()
000000001836e1e0 000007feea2657d4 System.IO.FileStream.Flush(Boolean)
000000001836e220 000007feea27128c System.IO.StreamWriter.Flush(Boolean, Boolean)
000000001836e280 000007fec064f2f7 Microsoft.VisualBasic.Logging.FileLogTraceListener+ReferencedStream.Flush()
000000001836e2d0 000007fec064e065 Microsoft.VisualBasic.Logging.FileLogTraceListener.Flush()
000000001836e300 000007fee92e0859 System.Diagnostics.TraceInternal.WriteLine(System.String)
000000001836e370 000007fe8bcc780d Neuron.Esb.ESBMasterService.Trace(System.Diagnostics.TraceListener, System.String)
000000001836e3c0 000007fe8bcc7bec Neuron.Esb.ESBMasterService.TraceInfo(System.Diagnostics.TraceSwitch, System.String, System.Diagnostics.TraceListener)
000000001836e420 000007fe8bfa72a9 Neuron.Esb.ESBMasterService.TraceInfo(System.Diagnostics.TraceSwitch, System.String)
000000001836e460 000007fe8c1c831e Neuron.Esb.EsbService.AmqpService.Trace(System.String, System.Object[])
000000001836e4a0 000007fe8cbbbc2e Neuron.Esb.EsbService.AmqpService.UpdateServiceStatus(Neuron.Esb.EsbService.ServiceState, Newtonsoft.Json.Linq.JToken)
000000001836e530 000007fe8c8baa0b Neuron.Esb.EsbService.AmqpService.UpdateExchangeStatus(System.Object, System.Timers.ElapsedEventArgs)
000000001836e5d0 000007fee9802586 System.Timers.Timer.MyTimerCallback(System.Object)
000000001836e650 000007feea1c2490 System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
000000001836e720 000007feea1c2327 System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
000000001836e750 000007feea1f0b9b System.Threading.TimerQueueTimer.CallCallback()
000000001836e7b0 000007feea1f0998 System.Threading.TimerQueueTimer.Fire()
000000001836e800 000007feea281a9f System.Threading.TimerQueue.FireNextTimers()
000000001836ed08 000007feeb303753 [DebuggerU2MCatchHandlerFrame: 000000001836ed08]
000000001836ee98 000007feeb303753 [ContextTransitionFrame: 000000001836ee98]
000000001836f0b8 000007feeb303753 [DebuggerU2MCatchHandlerFrame: 000000001836f0b8]

 

Having years of experience with log4net, I decided to use and recommend that.