SDbgExt 1.09 released (support for displaying x64 EH data)

I’ve put out SDbgExt 1.09. This is an incremental release of my collection of WinDbg debugger extensions.

The 1.09 release primarily adds support for displaying exception handler data on x64. While there is “some” built-in debugger support for this (via the “.fnent”) command, this support is extremely minimal. You are essentially required to dump the unwind data structures yourself and manually parse them out, which isn’t exactly fun. So, I added support for doing all of that hard work to SDbgExt, via the !fnseh SDbgExt extension (display function SEH data). This support is complementary to the !exchain command supplied by ext.dll for x86 targets.

The “!fnseh” command supports displaying most of the interesting fields of the unwind metadata (besides information on how the prologue works). It also properly supports chained unwind information records (both the documented and undocumented formats). There is also basic support for detecting and processing CL’s C/C++ exception scope tables, if a function uses C language exception handling (__try/__except/__finally).

Here’s a couple quick examples of it:

1: kd> !fnseh nt!CcPinRead
nt!CcPinRead L6a 2B,10 [ U ] nt!_C_specific_handler (C)
> fffff800012bf937 L2 (fffff800012fe4c0 -> fffff80001000000)
> fffff800012bf939 L16 (fffff800012fe4c0 -> fffff80001000000)
> fffff800012bf94f L5b (fffff800012fe4c0 -> fffff80001000000)
> fffff800012bf9aa L48 (fffff800012fe4c0 -> fffff80001000000)
> fffff800012c5199 Ld (fffff800012fe4c0 -> fffff80001000000)
> fffff800012c51a6 L58 (fffff800012fe4c0 -> fffff80001000000)
> fffff800012c51fe L1b (fffff800012fe4c0 -> fffff80001000000)
1: kd> !fnseh nt!CcCopyRead
nt!CcCopyRead Lae 3A,10 [E  ] nt!_C_specific_handler (C)
> fffff80001272c01 Lbf (fffff800012fe2e0 -> fffff800012c4c39)
> fffff80001272cc0 Lc (fffff800012fe2e0 -> fffff800012c4c39)
> fffff800012871f4 L2b (fffff800012fe2e0 -> fffff800012c4c39)
> fffff8000128721f L5a (fffff800012fe2e0 -> fffff800012c4c39)
> fffff800012961b1 L8 (fffff800012fe2c0 -> fffff800012c4b93)
> fffff800012961b9 L56 (fffff800012fe2c0 -> fffff800012c4b93)
> fffff800012c4aae Lcc (fffff800012fe2c0 -> fffff800012c4b93)
> fffff800012c4b7a L19 (fffff800012fe2c0 -> fffff800012c4b93)
1: kd> !fnseh nt!NtAllocateVirtualMemory
nt!NtAllocateVirtualMemory L5e 30,10 [E  ]
nt!_C_specific_handler (C)
> fffff8000103f74f L22 ( -> fffff8000103f771)
> fffff8000103f7f9 L16 ( -> fffff8000109adbf)
> fffff8000105ed3e L46 (fffff800010f3dc0 -> fffff8000105f173)
> fffff8000105f14d L22 ( -> fffff8000105f16f)
1: kd> !fnseh nt!KiSystemCall64
nt!KiSystemCall64 L390 50,0C [EU ]
nt!KiSystemServiceHandler (assembler/unknown)
0:000> !fnseh ntoskrnl + 00001180
401180 L2e 29,06 [  C] <none> (none)
 ntoskrnl!CcUnpinFileDataEx L32 13,05 [   ] <none> (none)

The basic output format is for unwind information as presented by the extension is as so:

EH-start-address LEH-effective-length prologue-size,unwind-code-count [unwind-flags (Exception handler, Unwind handler, Chained unwind information)] exception-handler (exception-handler-language)

Additionally, if the extension thinks that the function in question is using C language support, it will display each of the scope table entries as well (scope table entries divide up the various regions in a function that may have a __try or __except; there is typically only one lowest-level exception handler per function, with the scope table being used to implement multiple __try/__except clauses per function):

> EH-start-address LEH-effective-length (__except-filter-function (optional) -> __except-handler-function)

This information can be useful for tracking down exception filters and handlers to breakpoint on and the like, as EH registrations are completely isolated from code on x64. Note that not all functions may have exception or unwind handlers, as an unwind information is required to be provided for all x64 functions that modify the stack or call other functions.

For more information on how x64 exception handling works under the hood, you might look at my article on the subject, or skape’s paper about x64 Windows binary analysis.

7 Responses to “SDbgExt 1.09 released (support for displaying x64 EH data)”

  1. Igor Zayets says:

    It would be great to have absolute URLs in your posts instead of relative ones. Links like my article on the subject lead to http:///?p=11 URL from Outlook 2007 RSS agregator. Thanks in advance.

  2. Skywing says:

    Hmm. That kind of sucks; I was trying to use relative URIs instead of absolute so that things like using a different domain name or going by IP wouldn’t completely break. Didn’t know that it hosed the RSS feed, though…

  3. […] And a new version has just been released, with 64-bit support for EH Records! […]

  4. baboo says:

    cannot download in china :(

  5. Bob says:

    Is SdbExt still available anywhere? The I would have loved to use this today.… returns Page not found, and a cursory search with Google doesn’t turn up any mirrors.

    Thanks in advance, great blog.

  6. FlySky says:

    Hey there you’ve got an phenomenal set of extended functions. I am trying to use your LoadDLL code to load a new DLL with the debugger.
    Although when compiling I keep getting an error:
    error LNK2019: unresolved external symbol “unsigned __int64 __stdcall ExecuteRemoteCall(void *,void *,unsigned long,void *,unsigned long,unsigned char,unsigned long,void * *,unsigned long,unsigned char)” (?ExecuteRemoteCall@@YG_KPAX0K0KEKPAPAXKE@Z) referenced in function _LoadDLL
    fatal error LNK1120: 1 unresolved externals.
    What does this mean, do I need any extra include files? I am compiling on Visual Studio 2010 and I am having the Windows SDK installed aswell.
    Thanks in advance!.


  7. Skywing says:

    You should find the code for that function in Utilities.cpp in the sdbgext package.

    Note that I would recommend against using the undocumented APIs for non-debugger logic. The only reason why I used them in SDbgExt was to allow injecting a DLL into a native app. You probably don’t want this for your scenario and so I would use standard LoadLibrary/GetProcAddress/etc.