{"id":43613,"date":"2014-11-14T07:00:00","date_gmt":"2014-11-14T07:00:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/oldnewthing\/2014\/11\/14\/how-to-view-the-stack-of-a-user-mode-thread-when-its-kernel-stack-has-been-paged-out\/"},"modified":"2014-11-14T07:00:00","modified_gmt":"2014-11-14T07:00:00","slug":"how-to-view-the-stack-of-a-user-mode-thread-when-its-kernel-stack-has-been-paged-out","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/oldnewthing\/20141114-00\/?p=43613","title":{"rendered":"How to view the stack of a user-mode thread when its kernel stack has been paged out"},"content":{"rendered":"<p>\nSuppose you have a machine that has crashed,\nand your investigation shows that the reason is that there\nis a critical section that everybody is waiting for.\nWhile waiting for that critical section, work piles up,\nand eventually the machine keels over.\nSuppose further that this crash is given to you in the form\nof a kernel debugger.\n<\/p>\n<p>\nIn case it wasn&#8217;t obvious, by &#8220;you&#8221;\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2011\/02\/11\/10127845.aspx\">\nI mean &#8220;me&#8221;<\/a>.\n<\/p>\n<p>\nOkay, so the critical section that is the cause of the logjam\nis this one:\n<\/p>\n<pre>\n1: kd&gt; !cs CONTOSO!g_csDataLock\n-----------------------------------------\nCritical section   = 0x00007ff7f0ed2f68 (CONTOSO!g_csDataLock+0x0)\nDebugInfo          = 0x0000000022f2efd0\nLOCKED\nLockCount          = 0x5D\nWaiterWoken        = No\nOwningThread       = 0x0000000000004228\nRecursionCount     = 0x1\nLockSemaphore      = 0x17A0\nSpinCount          = 0x00000000020007cb\n<\/pre>\n<p>\n&#8220;Great,&#8221; you say.\n&#8220;I just need to look at thread 0x4228 to see why it is stuck.\n<\/p>\n<pre>\n1: kd&gt; !process -1 4\nPROCESS ffffe000047ae900\n    SessionId: 1  Cid: 0604    Peb: 7ff74ecfa000  ParentCid: 05cc\n    DirBase: 0eb07000  ObjectTable: ffffc000014c5680  HandleCount: 7003.\n    Image: contoso.exe\n        ...\n        THREAD ffffe0000c136080  Cid 0604.4228  Teb: 00007ff74e94c000 Win32Thread: fffff90144edea60 WAIT\n        ...\n<\/pre>\n<p>\nWoo-hoo, there&#8217;s the thread.\nNow I just need to switch to its context to see what it is stuck on.\n<\/p>\n<pre>\n1: kd&gt; .thread ffffe0000c136080\n<a HREF=\"https:\/\/www.youtube.com\/watch?v=1ytCEuuW2_A\">Can't retrieve thread context<\/a>, Win32 error 0n30\n<\/pre>\n<p>\nOkay, that didn&#8217;t work out too well.\nNow what?\n<\/p>\n<p>\nEven though the kernel stack is paged out,\nthe user-mode stack may still be available.\n<\/p>\n<pre>\n1: kd&gt; !thread ffffe0000c136080\nTHREAD ffffe0000c136080  Cid 0604.4228  Teb: <u>00007ff74e94c000<\/u>\n       Win32Thread: fffff90144edea60 WAIT: (UserRequest) UserMode Non-Alertable\n    ffffe000077a7830  NotificationEvent\nNot impersonating\nDeviceMap                 ffffc00000e89c80\nOwning Process            ffffe000047ae900       Image:         contoso.exe\nAttached Process          N\/A            Image:         N\/A\nWait Start TickCount      12735890       Ticks: 328715 (0:01:25:36.171)\nContext Switch Count      75             IdealProcessor: 2\nUserTime                  00:00:00.000\nKernelTime                00:00:00.031\nKernel stack not resident.\n<\/pre>\n<p>\nThe limits of the user-mode stack are kept in the Teb.\n<\/p>\n<pre>\n2: kd&gt; !teb 00007ff74e94c000\nTEB at 00007ff74e94c000\n    ExceptionList:        0000000000000000\n    <u>StackBase:            00000001027d0000<\/u>\n    <u>StackLimit:           00000001027c2000<\/u>\n    SubSystemTib:         0000000000000000\n    FiberData:            0000000000001e00\n    ArbitraryUserPointer: 0000000000000000\n    Self:                 00007ff74e94c000\n    EnvironmentPointer:   0000000000000000\n    ClientId:             0000000000000604 . 0000000000004228\n    RpcHandle:            0000000000000000\n    Tls Storage:          000000010132dfc0\n    PEB Address:          00007ff74ecfa000\n    LastErrorValue:       1008\n    LastStatusValue:      c0000034\n    Count Owned Locks:    2\n    HardErrorMode:        0\n<\/pre>\n<p>\nWe now use the trick we learned some time ago\nwhere we\n<a HREF=\"http:\/\/blogs.msdn.com\/b\/oldnewthing\/archive\/2012\/05\/17\/10306078.aspx\">\ngrovel the stack of a thread without knowing where its stack pointer is<\/a>.\n<\/p>\n<p>\nIn this case,\nthe groveling is made easier because we already know that\neverybody is waiting on the data lock.\nThe data lock is taken in only two functions,\nso it&#8217;s a matter ot looking for\nany occurrences of one of those two functions.\nAnd here it is:\n<code>Data&shy;Wrapper::Verify&shy;Data<\/code>.\n<\/p>\n<pre>\n00000001`027cef88  00007ffe`f1bbac9a NTDLL!NtWaitForSingleObject+0xa\n00000001`027cef90  00000000`00006ac8\n00000001`027cef98  00007ffe`ef1bd085 KERNELBASE!WaitForSingleObjectEx+0xa5\n00000001`027cefa0  00000000`00006ac8\n00000001`027cefa8  00000000`00000000\n00000001`027cefb0  00000000`026d0000\n00000001`027cefb8  00000000`00000000\n00000001`027cefc0  00000001`01739ee0\n00000001`027cefc8  00000000`00000001\n00000001`027cefd0  00000000`00000048\n00000001`027cefd8  00000001`00000001\n00000001`027cefe0  00000000`00000000\n00000001`027cefe8  00000000`00000000\n00000001`027ceff0  00000000`00000000\n00000001`027ceff8  00000000`00000000\n00000001`027cf000  00000000`00000000\n00000001`027cf008  00000000`00000000\n00000001`027cf010  00000000`00000000\n00000001`027cf018  00007ff7`eefe6540 FABRIKAM!Lock::IsInitialized+0xfc\n00000001`027cf020  00000000`00000000\n00000001`027cf028  00000000`3b803fa0\n00000001`027cf030  00000000`00006ac8\n00000001`027cf038  00007ff7`eeff3c43 FABRIKAM!AccessRequest::WaitTimeout+0x87\n00000001`027cf040  00000000`ffffffff\n00000001`027cf048  10f513ec`6a161fb8\n00000001`027cf050  00000000`00000000\n00000001`027cf058  00000000`00006ac8\n00000001`027cf060  00000000`3b803fb8\n00000001`027cf068  00007ff7`eeff3cc0 FABRIKAM!AccessRequest::Wait+0x18\n00000001`027cf070  00000000`8007000e\n00000001`027cf078  00000000`fd416ff0\n00000001`027cf080  4fe80c4a`51236583\n00000001`027cf088  00000000`3b803fb8\n00000001`027cf090  00000000`ffffffff\n00000001`027cf098  00000000`00000000\n00000001`027cf0a0  00000000`3b803fa0\n00000001`027cf0a8  00007ff7`da8375b7 FABRIKAM!DataAccess::RequestAccess+0x93\n00000001`027cf0b0  00000000`3b803fa0\n00000001`027cf0b8  00000000`3b803fb8\n00000001`027cf0c0  4fe80c4a`51236583\n00000001`027cf0c8  10f513ec`6a161fb8\n00000001`027cf0d0  00000000`00000076\n00000001`027cf0d8  00007ff7`f07a8619 CONTOSO!Widget::SetColor+0x9\n00000001`027cf0e0  000095dc`90897985\n00000001`027cf0e8  00000000`00000110\n00000001`027cf0f0  00000000`00000000\n00000001`027cf0f8  00000000`00000000\n00000001`027cf100  00007ff7`4dd8000c\n00000001`027cf108  00007ff7`f07a85e5 CONTOSO!Widget::UpdateColor+0x39\n00000001`027cf110  00000000`ffc03f90\n00000001`027cf118  00000001`027cf1e8\n00000001`027cf120  00000000`ffc03fc8\n00000001`027cf128  00000000`00000000\n00000001`027cf130  00000000`00000000\n00000001`027cf138  00007ff7`4dd8000c\n00000001`027cf140  00007ff7`da5bc420 FABRIKAM!DataAccess::`vftable'+0x18\n00000001`027cf148  00000000`ffc03f90\n00000001`027cf150  00000001`027cf260\n00000001`027cf158  00007ff7`f0b3459c CONTOSO!DataWrapper::VerifyData+0x428\n00000001`027cf160  00000000`3b803fa0\n00000001`027cf168  00007ff7`f0ed1d30 CONTOSO!g_DataManager\n00000001`027cf170  00000000`fe196f10\n00000001`027cf188  00000000`00000001\n00000001`027cf190  00000000`00000000\n00000001`027cf198  00000001`027cf270\n00000001`027cf1a0  00000001`027cf480\n00000001`027cf1a8  00007ff7`00000001\n00000001`027cf1b0  00000001`027cf220\n00000001`027cf1b8  00000000`00000000\n00000001`027cf1c0  00000000`00000000\n<\/pre>\n<p>\nI left the red herrings in place just to make things a little\nmore interesting.\n<\/p>\n<p>\nThe <code>Data&shy;Wrapper::Verify&shy;Data<\/code> method\nenters the critical section and then calls\n<code>Data&shy;Access::Request&shy;Access<\/code>\nvia a virtual method call:\n<\/p>\n<pre>\n00007ff7`f0b3458f mov     dword ptr [rsp+28h],eax\n00007ff7`f0b34593 mov     eax,dword ptr [rsi+10h]\n00007ff7`f0b34596 mov     dword ptr [rsp+20h],eax\n00007ff7`f0b3459a call    qword ptr [rdi] &larr;\n<\/pre>\n<p>\nLet&#8217;s disassemble the start of\n<code>Data&shy;Access::Request&shy;Access<\/code>\nto see how it sets up its stack.\nThis will help us interpret the other values in the stack dump.\n<\/p>\n<pre>\n0: kd&gt; u 00007ff7`da8375b7-93\nFABRIKAM!DataAccess::RequestAccess\n;; function prologue\n00007ff7`da837524 mov     rax,rsp\n00007ff7`da837527 mov     qword ptr [rax+8],rbx\n00007ff7`da83752b mov     qword ptr [rax+20h],r9\n00007ff7`da83752f mov     qword ptr [rax+18h],r8\n00007ff7`da837533 mov     qword ptr [rax+10h],rdx\n00007ff7`da837537 push    rbp\n00007ff7`da837538 push    rsi\n00007ff7`da837539 push    rdi\n00007ff7`da83753a push    r12\n00007ff7`da83753c push    r13\n00007ff7`da83753e push    r14\n00007ff7`da837540 push    r15\n00007ff7`da837542 sub     rsp,70h\n;; function body\n00007ff7`da837546 lea     rsi,[rcx+18h]\n00007ff7`da83754a mov     rdi,rcx\n00007ff7`da83754d mov     rbp,r9\n00007ff7`da837550 mov     rcx,rsi\n00007ff7`da837553 call    qword ptr [FABRIKAM!_imp_EnterCriticalSection]\n00007ff7`da837559 xor     r13b,r13b\n00007ff7`da83755c mov     ebx,8007000Eh\n...\n00007ffe`da8375b1 call    FABRIKAM!AccessRequest::Wait\n<\/pre>\n<p>\nWe can replay the above code in our head and annotate the stack\ntrace accordingly.\nOn entry to the function, the stack pointer is\n<code>00000001`027cf158<\/code> (the return address).\nThe function stashes some registers in the caller-provided spill area\nand it pushes others onto the stack,\nand then it subtracts some space for local variables\nas well as for outbound parameters of functions it intends to call.\n<\/p>\n<pre>\n\/-00000001`027cf0b0  00000000`3b803fa0\n| 00000001`027cf0b8  00000000`3b803fb8\n| 00000001`027cf0c0  4fe80c4a`51236583\n| 00000001`027cf0c8  10f513ec`6a161fb8\n| 00000001`027cf0d0  00000000`00000076\n| 00000001`027cf0d8  00007ff7`f07a8619 CONTOSO!Widget::SetColor+0x9\n| 00000001`027cf0e0  000095dc`90897985\n| 00000001`027cf0e8  00000000`00000110\n| 00000001`027cf0f0  00000000`00000000\n| 00000001`027cf0f8  00000000`00000000\n| 00000001`027cf100  00007ff7`4dd8000c\n| 00000001`027cf108  00007ff7`f07a85e5 CONTOSO!Widget::UpdateColor+0x39\n| 00000001`027cf110  00000000`ffc03f90\n\\-00000001`027cf118  00000001`027cf1e8\n  00000001`027cf120  00000000`ffc03fc8 <font COLOR=\"blue\">\/\/ VerifyData's r15<\/font>\n  00000001`027cf128  00000000`00000000 <font COLOR=\"blue\">\/\/ VerifyData's r14<\/font>\n  00000001`027cf130  00000000`00000000 <font COLOR=\"blue\">\/\/ VerifyData's r13<\/font>\n  00000001`027cf138  00007ff7`4dd8000c <font COLOR=\"blue\">\/\/ VerifyData's r12<\/font>\n  00000001`027cf140  00007ff7`da5bc420 FABRIKAM!DataAccess::`vftable'+0x18 <font COLOR=\"blue\">\/\/ VerifyData's rdi<\/font>\n  00000001`027cf148  00000000`ffc03f90 <font COLOR=\"blue\">\/\/ VerifyData's rsi<\/font>\n  00000001`027cf150  00000001`027cf260 <font COLOR=\"blue\">\/\/ VerifyData's rbp<\/font>\n  00000001`027cf158  00007ff7`f0b3459c CONTOSO!DataWrapper::VerifyData+0x428 <font COLOR=\"blue\">&larr; ESP is here<\/font>\n  00000001`027cf160  00000000`3b803fa0 <font COLOR=\"blue\">\/\/ VerifyData's rbx<\/font>\n  00000001`027cf168  00007ff7`f0ed1d30 CONTOSO!g_DataManager <font COLOR=\"blue\">\/\/ VerifyData's rdx<\/font>\n  00000001`027cf170  00000000`fe196f10 <font COLOR=\"blue\">\/\/ VerifyData's r8<\/font>\n  00000001`027cf188  00000000`00000001 <font COLOR=\"blue\">\/\/ VerifyData's r9<\/font>\n  00000001`027cf190  00000000`00000000\n  00000001`027cf198  00000001`027cf270\n  00000001`027cf1a0  00000001`027cf480\n  00000001`027cf1a8  00007ff7`00000001\n  00000001`027cf1b0  00000001`027cf220\n  00000001`027cf1b8  00000000`00000000\n  00000001`027cf1c0  00000000`00000000\n<\/pre>\n<p>\nThe region marked in brackets is the 0x70 bytes of space for local variables\nand outbound parameters.\nNotice that some red herring function pointers are in that space.\nThose are probably variables that haven&#8217;t been initialized yet,\nand the memory happened previously to have been used to hold some\nreturn addresses.\n<\/p>\n<p>\nA reassuring observation is that the <code>rdx<\/code>\ncoming from <code>Verify&shy;Data<\/code> is the address of\n<code>CONTOSO!g_Data&shy;Manager<\/code>.\nThat is the second function parameter (or first, if you aren&#8217;t\ncounting the hidden <code>this<\/code>)\nto <code>Request&shy;Access<\/code>.\n<\/p>\n<p>\nAnother reassuring observation is that\nthat <code>Verify&shy;Data<\/code>&#8216;s\n<code>rdi<\/code> points into the vtable for <code>Data&shy;Access<\/code>,\nsince that matches the code we saw at the call point:\n<code>call qword ptr [rdi]<\/code>.\n<\/p>\n<p>\nThe <code>mov rdi, rcx<\/code> instruction in the function body\ntells us that the function\nstashed its <code>this<\/code> pointer in <code>rdi<\/code>.\nThat&#8217;s good info to keep track of,\nbecause that will let us look at the <code>Data&shy;Access<\/code> object\nonce we figure out what is in <code>rdi<\/code>.\n<\/p>\n<p>\nThe next function on the stack is\n<code>Access&shy;Request::Wait<\/code>.\n<\/p>\n<pre>\nFABRIKAM!AccessRequest::Wait:\n00007ff7`eeff3ca8 sub     rsp,38h\n00007ffe`eeff3cb3 mov     dword ptr [rsp+20h],0FFFFFFFFh\n00007ffe`eeff3cbb call    FABRIKAM!AccessRequest::WaitTimeout\n00007ffe`eeff3cc0 add     rsp,38h\n00007ffe`eeff3cc4 ret\n<\/pre>\n<p>\nThis function doesn&#8217;t bother saving any registers;\nit just reserves space for local variables and outbound parameters.\nFrom inspection, you can see that this is a simple wrapper\nthat passes all its parameters onward to\n<code>Wait&shy;Timeout<\/code>,\nwith an <code>INFINITE<\/code> tacked onto the end,\nso this function has no local variables at all.\nEverything is just for outbound parameters.\n<\/p>\n<p>\nWe can annotate some more entries in our stack trace.\n<\/p>\n<pre>\n00000001`027cf070  00000000`8007000e <font COLOR=\"blue\">\/\/ spill space for WaitTimeout<\/font>\n00000001`027cf078  00000000`fd416ff0 <font COLOR=\"blue\">\/\/ spill space for WaitTimeout<\/font>\n00000001`027cf080  4fe80c4a`51236583 <font COLOR=\"blue\">\/\/ spill space for WaitTimeout<\/font>\n00000001`027cf088  00000000`3b803fb8 <font COLOR=\"blue\">\/\/ spill space for WaitTimeout<\/font>\n00000001`027cf090  00000000`ffffffff <font COLOR=\"blue\">\/\/ INFINITE parameter<\/font>\n00000001`027cf098  00000000`00000000 <font COLOR=\"blue\">\/\/ unused<\/font>\n00000001`027cf0a0  00000000`3b803fa0 <font COLOR=\"blue\">\/\/ unused<\/font>\n00000001`027cf0a8  00007ff7`da8375b7 FABRIKAM!DataAccess::RequestAccess+0x93\n<\/pre>\n<p>\nThe next function on the list is\n<code>Access&shy;Request::Wait&shy;Timeout<\/code>.\n<\/p>\n<pre>\nFABRIKAM!AccessRequest::WaitTimeout:\n00007ff7`eeff3bbc mov     qword ptr [rsp+8],rbx\n00007ff7`eeff3bc1 mov     qword ptr [rsp+10h],rbp\n00007ff7`eeff3bc6 push    rsi\n00007ff7`eeff3bc7 sub     rsp,20h\n00007ff7`eeff3bcb mov     ebx,edx\n00007ff7`eeff3bcd mov     rsi,rcx\n00007ff7`eeff3bd0 mov     edx,0Bh\n00007ff7`eeff3bd5 mov     rcx,r8\n<\/pre>\n<p>\nThis function stashes two registers in the parameter spill space,\npushes one onto the stack,\nand reserves another 0x20 bytes for local use (outbound parameters).\n<\/p>\n<pre>\n00000001`027cf040  00000000`ffffffff <font COLOR=\"blue\">\/\/ spill space for WaitForSingleObjectEx<\/font>\n00000001`027cf048  10f513ec`6a161fb8 <font COLOR=\"blue\">\/\/ spill space for WaitForSingleObjectEx<\/font>\n00000001`027cf050  00000000`00000000 <font COLOR=\"blue\">\/\/ spill space for WaitForSingleObjectEx<\/font>\n00000001`027cf058  00000000`00006ac8 <font COLOR=\"blue\">\/\/ spill space for WaitForSingleObjectEx<\/font>\n00000001`027cf060  00000000`3b803fb8 <font COLOR=\"blue\">\/\/ Wait's rsi<\/font>\n00000001`027cf068  00007ff7`eeff3cc0 FABRIKAM!AccessRequest::Wait+0x18\n00000001`027cf070  00000000`8007000e <font COLOR=\"blue\">\/\/ Wait's rbx<\/font>\n00000001`027cf078  00000000`fd416ff0\n00000001`027cf080  4fe80c4a`51236583\n00000001`027cf088  00000000`3b803fb8\n<\/pre>\n<p>\nNotice that the stashed <code>rbx<\/code> value is <code>8007000E<\/code>,\nwhich conveniently lines up with the\n<code>mov ebx,8007000Eh<\/code>\ninstruction in\n<code>Data&shy;Access::Request&shy;Access<\/code>.\nThat&#8217;s a bit reassuring, since it&#8217;s another sign that we&#8217;re\non the right track.\n<\/p>\n<p>\nNext up is\n<code>Wait&shy;For&shy;Single&shy;Object&shy;Ex<\/code>.\n<\/p>\n<pre>\n0: kd&gt; u 00007ffe`ef1bd085 -a5\nKERNELBASE!WaitForSingleObjectEx\n00007ffe`ef1bcfe0 mov     r11,rsp\n00007ffe`ef1bcfe3 mov     qword ptr [r11+8],rbx\n00007ffe`ef1bcfe7 mov     dword ptr [r11+18h],r8d\n00007ffe`ef1bcfeb push    rsi\n00007ffe`ef1bcfec push    rdi\n00007ffe`ef1bcfed push    r14\n00007ffe`ef1bcfef sub     rsp,80h\n00007ffe`ef1bcff6 mov     ebx,r8d\n<\/pre>\n<p>\nIncorporating this prologue into our stack annotation yields\n<\/p>\n<pre>\n\/-00000001`027cefa0  00000000`00006ac8 <font COLOR=\"blue\">\/\/ spill space for NtWaitForSingleObject<\/font>\n| 00000001`027cefa8  00000000`00000000 <font COLOR=\"blue\">\/\/ spill space for NtWaitForSingleObject<\/font>\n| 00000001`027cefb0  00000000`026d0000 <font COLOR=\"blue\">\/\/ spill space for NtWaitForSingleObject<\/font>\n| 00000001`027cefb8  00000000`00000000 <font COLOR=\"blue\">\/\/ spill space for NtWaitForSingleObject<\/font>\n| 00000001`027cefc0  00000001`01739ee0\n| 00000001`027cefc8  00000000`00000001\n| 00000001`027cefd0  00000000`00000048\n| 00000001`027cefd8  00000001`00000001\n| 00000001`027cefe0  00000000`00000000\n| 00000001`027cefe8  00000000`00000000\n| 00000001`027ceff0  00000000`00000000\n| 00000001`027ceff8  00000000`00000000\n| 00000001`027cf000  00000000`00000000\n| 00000001`027cf008  00000000`00000000\n| 00000001`027cf010  00000000`00000000\n\\-00000001`027cf018  00007ff7`eefe6540 FABRIKAM!Lock::IsInitialized+0xfc\n  00000001`027cf020  00000000`00000000 <font COLOR=\"blue\">\/\/ WaitTimeout's r14<\/font>\n  00000001`027cf028  00000000`3b803fa0 <font COLOR=\"blue\">\/\/ WaitTimeout's rdi<\/font>\n  00000001`027cf030  00000000`00006ac8 <font COLOR=\"blue\">\/\/ WaitTimeout's rsi<\/font>\n  00000001`027cf038  00007ff7`eeff3c43 FABRIKAM!AccessRequest::WaitTimeout+0x87\n  00000001`027cf040  00000000`ffffffff <font COLOR=\"blue\">\/\/ WaitTimeout's rbx<\/font>\n  00000001`027cf048  10f513ec`6a161fb8\n  00000001`027cf050  00000000`00000000 <font COLOR=\"blue\">\/\/ WaitTimeout's r8<\/font>\n  00000001`027cf058  00000000`00006ac8\n<\/pre>\n<p>\nOoh, another red herring function pointer got caught in the local\nvariables.\n<\/p>\n<p>\nPutting everything together results in the following annotated stack,\nwith red herrings removed.\n<\/p>\n<pre>\n00000001`027cef88  00007ffe`f1bbac9a NTDLL!NtWaitForSingleObject+0xa\n00000001`027cef90  00000000`00006ac8\n00000001`027cef98  00007ffe`ef1bd085 KERNELBASE!WaitForSingleObjectEx+0xa5\n00000001`027cefa0  00000000`00006ac8\n00000001`027cefa8  00000000`00000000\n00000001`027cefb0  00000000`026d0000\n00000001`027cefb8  00000000`00000000\n00000001`027cefc0  00000001`01739ee0\n00000001`027cefc8  00000000`00000001\n00000001`027cefd0  00000000`00000048\n00000001`027cefd8  00000001`00000001\n00000001`027cefe0  00000000`00000000\n00000001`027cefe8  00000000`00000000\n00000001`027ceff0  00000000`00000000\n00000001`027ceff8  00000000`00000000\n00000001`027cf000  00000000`00000000\n00000001`027cf008  00000000`00000000\n00000001`027cf010  00000000`00000000\n00000001`027cf018  00007ff7`eefe6540\n00000001`027cf020  00000000`00000000 <font COLOR=\"blue\">\/\/ WaitTimeout's r14<\/font>\n00000001`027cf028  00000000`3b803fa0 <font COLOR=\"blue\">\/\/ WaitTimeout's rdi<\/font>\n00000001`027cf030  00000000`00006ac8 <font COLOR=\"blue\">\/\/ WaitTimeout's rsi<\/font>\n00000001`027cf038  00007ff7`eeff3c43 FABRIKAM!AccessRequest::WaitTimeout+0x87\n00000001`027cf040  00000000`ffffffff <font COLOR=\"blue\">\/\/ WaitTimeout's rbx<\/font>\n00000001`027cf048  10f513ec`6a161fb8\n00000001`027cf050  00000000`00000000 <font COLOR=\"blue\">\/\/ WaitTimeout's r8<\/font>\n00000001`027cf058  00000000`00006ac8\n00000001`027cf060  00000000`3b803fb8 <font COLOR=\"blue\">\/\/ Wait's rsi<\/font>\n00000001`027cf068  00007ff7`eeff3cc0 FABRIKAM!AccessRequest::Wait+0x18\n00000001`027cf070  00000000`8007000e <font COLOR=\"blue\">\/\/ Wait's rbx<\/font>\n00000001`027cf078  00000000`fd416ff0\n00000001`027cf080  4fe80c4a`51236583\n00000001`027cf088  00000000`3b803fb8\n00000001`027cf090  00000000`ffffffff <font COLOR=\"blue\">\/\/ INFINITE parameter<\/font>\n00000001`027cf098  00000000`00000000\n00000001`027cf0a0  00000000`3b803fa0\n00000001`027cf0a8  00007ff7`da8375b7 FABRIKAM!DataAccess::RequestAccess+0x93\n00000001`027cf0b0  00000000`3b803fa0\n00000001`027cf0b8  00000000`3b803fb8\n00000001`027cf0c0  4fe80c4a`51236583\n00000001`027cf0c8  10f513ec`6a161fb8\n00000001`027cf0d0  00000000`00000076\n00000001`027cf0d8  00007ff7`f07a8619\n00000001`027cf0e0  000095dc`90897985\n00000001`027cf0e8  00000000`00000110\n00000001`027cf0f0  00000000`00000000\n00000001`027cf0f8  00000000`00000000\n00000001`027cf100  00007ff7`4dd8000c\n00000001`027cf108  00007ff7`f07a85e5\n00000001`027cf110  00000000`ffc03f90\n00000001`027cf118  00000001`027cf1e8\n00000001`027cf120  00000000`ffc03fc8 <font COLOR=\"blue\">\/\/ VerifyData's r15<\/font>\n00000001`027cf128  00000000`00000000 <font COLOR=\"blue\">\/\/ VerifyData's r14<\/font>\n00000001`027cf130  00000000`00000000 <font COLOR=\"blue\">\/\/ VerifyData's r13<\/font>\n00000001`027cf138  00007ff7`4dd8000c <font COLOR=\"blue\">\/\/ VerifyData's r12<\/font>\n00000001`027cf140  00007ff7`da5bc420 FABRIKAM!DataAccess::`vftable'+0x18 <font COLOR=\"blue\">\/\/ VerifyData's rdi<\/font>\n00000001`027cf148  00000000`ffc03f90 <font COLOR=\"blue\">\/\/ VerifyData's rsi<\/font>\n00000001`027cf150  00000001`027cf260 <font COLOR=\"blue\">\/\/ VerifyData's rbp<\/font>\n00000001`027cf158  00007ff7`f0b3459c CONTOSO!DataWrapper::VerifyData+0x428\n00000001`027cf160  00000000`3b803fa0 <font COLOR=\"blue\">\/\/ VerifyData's rbx<\/font>\n00000001`027cf168  00007ff7`f0ed1d30 CONTOSO!g_DataManager <font COLOR=\"blue\">\/\/ VerifyData's rdx<\/font>\n00000001`027cf170  00000000`fe196f10 <font COLOR=\"blue\">\/\/ VerifyData's r8<\/font>\n00000001`027cf188  00000000`00000001 <font COLOR=\"blue\">\/\/ VerifyData's r9<\/font>\n00000001`027cf190  00000000`00000000\n00000001`027cf198  00000001`027cf270\n00000001`027cf1a0  00000001`027cf480\n00000001`027cf1a8  00007ff7`00000001\n00000001`027cf1b0  00000001`027cf220\n00000001`027cf1b8  00000000`00000000\n00000001`027cf1c0  00000000`00000000\n<\/pre>\n<p>\nFrom this, we can also suck out the\n<code>this<\/code> pointer passed to\n<code>Data&shy;Access::Request&shy;Access<\/code>.\nWe saw that it was stashed in <code>rdi<\/code>.\nThe <code>Wait<\/code> function doesn&#8217;t use <code>rdi<\/code>\n(because if it did, it would have saved the old value),\nso its <code>rdi<\/code> is the same as\n<code>Request&shy;Access<\/code>&#8216;s <code>rdi<\/code>.\nSimilarly, the\n<code>Wait&shy;Timeout<\/code> function does not use <code>rdi<\/code>.\nTherefore, when\n<code>Wait&shy;For&shy;Single&shy;Object<\/code> saves the\n<code>rdi<\/code> register,\nit is saving the value from\n<code>Data&shy;Access::Request&shy;Access<\/code>.\n<\/p>\n<pre>\n00000001`027cf028  00000000`3b803fa0 <font COLOR=\"blue\">\/\/ <strike>WaitTimeout<\/strike> DataAccess's rdi<\/font>\n<\/pre>\n<p>\nAnd that is the <code>this<\/code> pointer that lets us\nstudy the\n<code>Data&shy;Access<\/code> object to figure out why\nits access request is not completing.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Suppose you have a machine that has crashed, and your investigation shows that the reason is that there is a critical section that everybody is waiting for. While waiting for that critical section, work piles up, and eventually the machine keels over. Suppose further that this crash is given to you in the form of [&hellip;]<\/p>\n","protected":false},"author":1069,"featured_media":111744,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[26],"class_list":["post-43613","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oldnewthing","tag-other"],"acf":[],"blog_post_summary":"<p>Suppose you have a machine that has crashed, and your investigation shows that the reason is that there is a critical section that everybody is waiting for. While waiting for that critical section, work piles up, and eventually the machine keels over. Suppose further that this crash is given to you in the form of [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/43613","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/users\/1069"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/comments?post=43613"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/posts\/43613\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media\/111744"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/media?parent=43613"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/categories?post=43613"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/oldnewthing\/wp-json\/wp\/v2\/tags?post=43613"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}