Today I'm looking at a few Watson dumps trying to determine why SqlConnection is failing to connect to SQL Server and hanging.

I see stack like below:

0:000> k
0021dc5c 79f40778 kernel32!SleepEx+0x62
0021dc90 7a0561d7 mscorwks!EESleepEx+0xa3
0021dc9c 7a12fc71 mscorwks!CExecutionEngine::ClrSleepEx+0xd
0021dcac 7a0e4d7c mscorwks!ClrSleepEx+0x13
0021dce8 7a082a5f mscorwks!Thread::UserSleep+0x63
0021dd88 652e94cd mscorwks!ThreadNative::Sleep+0xce
0021ddc8 652e9283 System_Data_ni!System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover
0021de20 652e83ff System_Data_ni!System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist

 

I need to look at CLR locals in SqlClient.SqlInternalConnectionTds.LoginNoFailover, and these locals are intrinsic CLR type long (Int64).

Where does CLR hide these frame local long values?

Using the sos extension I see !dso does not dump intrinsic locals.

!clrstack, wow the output is completely wrong and bizarre.

!dumpstack, !dumpstack -EE, broken.

kP works, somewhat reasonably.

Time to get ugly.

Ok, I locate start of assembly for SqlInternalConnectionTds.LoginNoFailover in debugger and just dump the raw assembly.

I know my variable is passed into function ADP.TimerRemainingMilliseconds, so my plan is to locate this call in unassembly and see how the assembly code packs the value passed to this function, this will give me a clue on where the value is held.

I find it here:

652e942f ff75d8          push    dword ptr [ebp-28h]
652e9432 ff75d4          push    dword ptr [ebp-2Ch]
652e9435 e8d2c3f3ff      call    System_Data_ni!System.Data.Common.ADP.TimerRemainingMilliseconds(Int64) (6522580c)

Good, I see ebp-offset, this looks like stack local.  I use kvn to get frame number.

0:000> kvn 10
# ChildEBP RetAddr  Args to Child             
...
07 0021dd88 652e94cd 06bf6a58 06bf3f90 06bf67cc mscorwks!ThreadNative::Sleep+0xce (FPO: [Non-Fpo]) (CONV: fastcall) [f:\whidbeyrtmlhs\ndp\clr\src\vm\comsynchronizable.cpp @ 964]
08 0021ddc8 652e9283 00000000 00000000 00000000 System_Data_ni!System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(System.String, System.String, Boolean, System.Data.SqlClient.SqlConnection, System.Data.SqlClient.SqlConnectionString, Int64)+0x215 (Managed) [f:\WhidbeyRTMlhs\ndp\fx\src\Data\System\Data\SqlClient\SqlInternalConnectionTds.cs @ 862]

Set the frame:

0:000> .frame 8
08 0021ddc8 652e9283 System_Data_ni!System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(System.String, System.String, Boolean, System.Data.SqlClient.SqlConnection, System.Data.SqlClient.SqlConnectionString, Int64)+0x215 [f:\WhidbeyRTMlhs\ndp\fx\src\Data\System\Data\SqlClient\SqlInternalConnectionTds.cs @ 862]

I then look at registers for frame 8:

0:000> r
Last set context:
eax=00000000 ebx=00000000 ecx=00000000 edx=00000000 esi=0021dc38 edi=00000000
eip=77520f34 esp=0021dbf4 ebp=0021dc5c iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00200202
ntdll!KiFastSystemCallRet:
77520f34 c3              ret

Ok, then 0021dc5c -28 and 0021dc5c -2c should be the 2 DWORDs that compose my Int64 value:

0:000> dd 0021dc5c-2c
0021dc30  76f16110 00000000

For real?  I am really not sure.  I'll try it on a live debug to be sure.