• Ntdebugging Blog

    Debugging a Windows 8.1 Store App Crash Dump

    • 0 Comments

    Quality reports on the App Summary page

    Microsoft provides triage dumps of your Windows Store application’s crashes and hangs through the Quality section of the App Summary page on the Dev Center - Windows Store apps portal.

     

    Back in June 2012, the Windows Store team posted an article on this feature and the basics of debugging the dumps provided.  Improving apps with Quality reports,

    http://blogs.msdn.com/b/windowsstore/archive/2012/06/27/improving-apps-with-quality-reports.aspx.

     

    This article digs further into the debugging of Windows Store application crash dump files, and explains the recent changes made to exception reporting in Windows 8.1.

     

    The files being debugged can be obtained from the Quality page or by collecting them yourself using Windows Error Reporting (WER) or the AeDebug feature of Windows.

     

    An example AeDebug tool is Sysinternals ProcDump. To configure crash dumping, execute the following from an elevated command prompt:

     

    C:\>md c:\dumps

    C:\>procdump.exe -ma -i c:\dumps

     

    Windows Runtime Architecture

    The Windows Runtime (WinRT API) is at the core of all Windows Store applications. Similar to how Win32 and.NET sit between the Desktop app and the kernel, the WinRT API sits between the Windows Store app and the kernel.

     

     

    In between the WinRT API and app is a layer called the Language Projection layer. This layer projects the C++ centric concepts of WinRT, into language specific concepts.

     

    The projection of errors through the Language Projection layer is the focus of this article.

    • In WinRT, errors are modeled as IErrorInfo and IRestrictedErrorInfo interfaces.
    • In CLR languages, errors are modeled as exceptions and are represented as class objects derived from System.Exception.
    • In JavaScript, errors are also modeled as exceptions and are represented as JavaScript Exception (JSE) objects.
    • In C/C++, errors are modeled as an interface or a pure HRESULT.

     

     

    Because each language has a different concept on how errors are handled, the projection layer needs to use a least common denominator. For errors, that means that just an HRESULT (Error Code) and HSTRING (Error Message) are sent through the projection layer. Any addition information held by WinRT’s interface is not available in the receiving language. And conversely, any additional information held by the language’s object is not available to WinRT.

     

    If the error becomes unhandled, the HRESULT becomes the Exception Code reported in the Exception Record (of a live debug session or dump file).

     

    Visual Studio 2013

    Opening a dump file in Visual Studio allows you to see the Exception Record via the MiniDump File Summary. The Exception Code is listed in the Dump Summary section.

     

    MinidumpFileSummary

     

    If you Debug the application, the Exception Code‘s Description will be listed in the Output window.

     

    OutputWindow

     

    The call stack of the Exception Record’s context is viewable in the Call Stack window. Depending on the dump’s state, the $exceptionstack pseudo variable can be used in a Watch (or Locals) window to see the stack.

     

    VisualStudio-CallStack

     

    Note, having the Private PDBs of the application will make the stack output more complete/accurate.

     

    Debugging Tools for Windows

    Using the Debugging Tools for Windows, the Exception Record can be displayed using the .exr -1 command. The Exception Code’s description can (sometimes) be looked up using the !error <code> command. The context of the exception is changed to with the .ecxr command. The stack is displayed with the k command (knL adds frame numbers and omits source line information).

     

    0:004> .exr -1

    ExceptionAddress: 722248e8 (msvcr110!Concurrency::details::_ReportUnobservedException+0x00000022)

       ExceptionCode: c0000409 (Security check failure or stack buffer overrun)

      ExceptionFlags: 00000001

    NumberParameters: 1

       Parameter[0]: 00000005

     

    0:004> !error c0000409

    Error code: (NTSTATUS) 0xc0000409 (3221226505) - The system detected an overrun of a stack-based buffer in this application. This overrun could potentially allow a malicious user to gain control of this application.

     

    0:004> .ecxr

    eax=00000001 ebx=ffffffff ecx=00000005 edx=0a6ee048 esi=13672424 edi=0546c33c

    eip=722248e8 esp=02ceeef8 ebp=02ceef14 iopl=0         nv up ei pl nz na po nc

    cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000202

    msvcr110!Concurrency::details::_ReportUnobservedException+0x22:

    722248e8 cd29            int     29h

     

    0:004> knL

      *** Stack trace for last set context - .thread/.cxr resets it

    # ChildEBP RetAddr 

    00 02ceeef4 00f2f6cb msvcr110!Concurrency::details::_ReportUnobservedException+0x22

    WARNING: Stack unwind information not available. Following frames may be wrong.

    01 02ceef14 00f2fad7 MyBadApp+0xef6cb

    02 02ceef40 01122720 MyBadApp+0xefad7

    03 02ceef64 011228eb MyBadApp+0x2e2720

    04 02ceef70 00f3960a MyBadApp+0x2e28eb

    05 02ceefb0 010cc804 MyBadApp+0xf960a

    06 02ceefc0 0112108e MyBadApp+0x28c804

    07 02ceeff8 72422b61 MyBadApp+0x2e108e

    08 02cef034 72427e27 Microsoft_Xbox!DllGetClassObject+0x61352

    09 02cef040 76095c3e Microsoft_Xbox!DllGetClassObject+0x66618

    0a 02cef060 7610f497 rpcrt4!Invoke+0x2a

    0b 02cef6ec 75c241f8 rpcrt4!NdrStubCall2+0x33c

    0c 02cef734 75c1f58a combase!CStdStubBuffer_Invoke+0xc1

    0d 02cef7c0 75b24617 combase!SyncStubInvoke+0x144

    0e (Inline) -------- combase!StubInvoke+0x9a

    0f 02cef8e8 75b97d8d combase!CCtxComChnl::ContextInvoke+0x222

    10 02cef90c 75c24cc9 combase!DefaultInvokeInApartment+0x30

    11 (Inline) -------- combase!ASTAInvokeInApartment+0x35

    12 02cef9b4 75c1fdc7 combase!AppInvoke+0x5ae

    13 02cefb00 75c24c71 combase!ComInvokeWithLockAndIPID+0x5ed

    14 02cefb20 75b93118 combase!ComInvoke+0x153

    15 02cefb30 75b97b11 combase!ThreadDispatch+0x23

    16 02cefb44 75be53b5 combase!CComApartment::ASTAHandleMessage+0xe6

    17 02cefb68 75ba8f22 combase!ASTAWaitContext::DispatchCallsOnExitNonBlockingProcessEventsIfAppropriate+0x9e

    18 02cefb8c 75b5917e combase!ASTAWaitContext::~ASTAWaitContext+0x1a9

    19 02cefb98 74acb13d combase!CoEndProcessEvents+0x37

    1a 02cefbf4 00f733d7 windows_ui!Windows::UI::Core::CDispatcher::ProcessEvents+0x29ac1

    1b 02cefc64 00f77f46 MyBadApp+0x1333d7

    1c 02cefc94 74f6f45e MyBadApp+0x137f46

    1d 02cefca0 74f6f322 twinapi_appcore!Windows::ApplicationModel::Core::CoreApplicationView::Run+0x27

    1e 02cefcc0 74b1008a twinapi_appcore!<lambda_f0454c86bc54370cf843d844d6c13e00>::operator()+0xb2

    1f 02cefd44 75f4a534 SHCore!_WrapperThreadProc+0xe2

    20 02cefd50 77dd8f8b kernel32!BaseThreadInitThunk+0xe

    21 02cefd94 77dd8f61 ntdll!__RtlUserThreadStart+0x20

    22 02cefda4 00000000 ntdll!_RtlUserThreadStart+0x1b

     

    Simple so far...

    Using Visual Studio or the Debugging Tools for Windows is relatively simple when the Exception Record is associated with the call stack of the issue. This is not however always the case. It depends on what side of the projection layer the issue occurred. If the error (exception) was not handled on the language side, the exception is marshaled (projected) to the WinRT side for its exception handling. When this occurs, it starts getting very, very tricky indeed, to see what stack caused the issue...

     

    Language Exceptions - Error Code 0xC000027B

    In the initial design of the WinRT API, the projection of errors was done though a call to the RoOriginateError function. This function takes a HRESULT and HSTRING. Of note, there is no call stack captured. The limits of the RoOriginateError function were recognized and a new (associated) function was created for Windows 8.1.

     

    The RoOriginateLanguageException function takes a HRESULT, HSTRING and a marshalable interface pointer. When RoOriginateLanguageException in called, the current call stack is captured and is passed as part of the error.

     

    The purpose of RoOriginateLanguageException is to marshal the interface pointer so that additional language information is available on the other side of the projection layer. This behavior is achieved by using a specific exception code. Instead of the using the (user defined) HRESULT, a value of 0xC000027B is used. This error code indicates to the receiver that there is data to unmarshal. The data includes the HRESULT and HSTRING, and also the Interface pointer.

     

    The important point to understand here is that all async exceptions raised in Windows 8.1 Windows Store apps now result in a 0xC000027B error code in the Exception Record, not the error code passed by the caller.

     

    Debugging Language Exceptions

    The Exception Record of a Language Exception contains (of note) the exception code (0xC000027B) and two parameters.

     

    0:004> .exr -1

    ExceptionAddress: 73034fec (Windows_UI_Xaml!DirectUI::ErrorHelper::ProcessUnhandledError+0x000000b8)

       ExceptionCode: c000027b

      ExceptionFlags: 00000001

    NumberParameters: 2

       Parameter[0]: 0bdaf240

       Parameter[1]: 00000001

     

    0:006> !error c000027b

    Error code: (NTSTATUS) 0xc000027b (3221226107) - An application-internal exception has occurred.

     

    The first parameter is the address of a pointer array (of unmarshalled data). The second parameter is the count of pointers in the pointer array.

     

    So why is the need for a count?  Since applications have multiple threads, it is possible for multiple threads to call RoOriginateLanguageException simultaneously. Equally, there can be a cyclic nature to the experience, where exceptions are caught and then re-thrown. Since WinRT processes the errors asynchronously, multiple errors exist regularly. The first exception in the array should be the focus of the investigation.

     

    [Tip] Even though Microsoft publishes the private symbols for combase.dll (allowing you to view the local variables of combase!RoFailFast* functions), these locals regularly resolve to invalid addresses due to register reuse and other code flow optimizations. The pointer array in Parameter[0] is the correct place to get the address of the language exception pointer array.

     

    Original Error Code

    The first step when debugging a Language Exception is to determine the actual error code of the caller, instead of the 0xC000027B error code.

     

    Casting an address to a pointer array of a specific type in Visual Studio is, put simply, too difficult to undertake. The easiest option is to use the Debugging Tools for Windows. Even though these tools are all command-line driven and use an obscure syntax, it is relatively easy to follow the following commands to get to the important information.

     

    If not done already, set your symbol path to the Microsoft Public Symbol server:

     

    0:004> .sympath SRV*C:\Symbols*http://msdl.microsoft.com/download/symbols

    Symbol search path is: SRV*C:\Symbols*http://msdl.microsoft.com/download/symbols

    Expanded Symbol search path is: srv*c:\Symbols*http://msdl.microsoft.com/download/symbols

    ************* Symbol Path validation summary **************

    Response                         Time (ms)     Location

    Deferred                                       SRV*C:\Symbols*http://msdl.microsoft.com/download/symbols

     

    Force the load of the symbols using the .reload /f command:

     

    0:004> .reload /f

    ...

     

    The next step is to display the pointer array as the original structure type. First, we need to know what structure to cast the pointer array to. Using the Parameter[0] value from .exr -1, we will generate a dt command that will display the header of the first record. We use Parameter[0] as the address in this command.

     

    dt <Parameter[0]> combase!_STOWED_EXCEPTION_INFORMATION_HEADER*

     

    Here’s an example:

     

    0:004> .exr -1

    ExceptionAddress: 73034fec (Windows_UI_Xaml!DirectUI::ErrorHelper::ProcessUnhandledError+0x000000b8)

       ExceptionCode: c000027b

      ExceptionFlags: 00000001

    NumberParameters: 2

       Parameter[0]: 0180cf90

       Parameter[1]: 00000003

     

    0:004> dt 0180cf90 combase!_STOWED_EXCEPTION_INFORMATION_HEADER*

    0x070884a4

       +0x000 Size             : 0x20

       +0x004 Signature        : 0x53453031

     

    The value of the Signature member (0x53453031) is converted to a string using .formats <value>.

     

    0:006> .formats 0x53453031

    Evaluate expression:

      Hex:     53453031

      Decimal: 1397043249

      Octal:   12321230061

      Binary:  01010011 01000101 00110000 00110001

      Chars:   SE01

      Time:    Wed Apr 09 04:34:09 2014

      Float:   low 8.46917e+011 high 0

      Double:  6.90231e-315

     

    The chars “SE01” map to a structure name of combase!_STOWED_EXCEPTION_INFORMATION_V1. It can be assumed that v2 uses a signature of “SE02” and a structure name of combase!_STOWED_EXCEPTION_INFORMATION_V2, and so on…

     

    Now we know the type, we can again use the values from .exr -1 to generate a dt command that will display each record. We use the Parameter[0] as the address, and Parameter[1] as the count in the command. We add an “*” to the end of the type as this is an array of pointers to the type, not structures packed next to each other.

     

    In this example, there are 3 pointers, so 3 records are displayed:

     

    dt -a<Parameter[1]> <Parameter[0]> combase!_STOWED_EXCEPTION_INFORMATION_V1*

     

    Note, there is no space between the -a and <Parameter[1]>.

     

    0:004> .exr -1

    ExceptionAddress: 73034fec (Windows_UI_Xaml!DirectUI::ErrorHelper::ProcessUnhandledError+0x000000b8)

       ExceptionCode: c000027b

      ExceptionFlags: 00000001

    NumberParameters: 2

       Parameter[0]: 0180cf90

       Parameter[1]: 00000003

     

    0:004> dt -a3 0180cf90 combase!_STOWED_EXCEPTION_INFORMATION_V1*

    [0] @ 0180cf90

    ---------------------------------------------

    0x070884a4

       +0x000 Header           : _STOWED_EXCEPTION_INFORMATION_HEADER

       +0x008 ResultCode       : 80131500

       +0x00c ExceptionForm    : 0y01

       +0x00c ThreadId         : 0y000000000000000000010100111100 (0x53c)

       +0x010 ExceptionAddress : 0x7721ea23 Void

       +0x014 StackTraceWordSize : 4

       +0x018 StackTraceWords  : 5

       +0x01c StackTrace       : 0x06f48418 Void

       +0x010 ErrorText        : 0x7721ea23  "?????"

     

    [1] @ 0180cf94

    ---------------------------------------------

    0x071ca274

       +0x000 Header           : _STOWED_EXCEPTION_INFORMATION_HEADER

       +0x008 ResultCode       : 80131500

       +0x00c ExceptionForm    : 0y01

       +0x00c ThreadId         : 0y000000000000000000010100111100 (0x53c)

       +0x010 ExceptionAddress : (null)

       +0x014 StackTraceWordSize : 4

       +0x018 StackTraceWords  : 0x19

       +0x01c StackTrace       : 0x071c926c Void

       +0x010 ErrorText        : (null)

     

    [2] @ 0180cf98

    ---------------------------------------------

    0x071c922c

       +0x000 Header           : _STOWED_EXCEPTION_INFORMATION_HEADER

       +0x008 ResultCode       : 80131534

       +0x00c ExceptionForm    : 0y01

       +0x00c ThreadId         : 0y000000000000000000010100111100 (0x53c)

       +0x010 ExceptionAddress : (null)

       +0x014 StackTraceWordSize : 4

       +0x018 StackTraceWords  : 9

       +0x01c StackTrace       : 0x071c8224 Void

       +0x010 ErrorText        : (null)

     

    The ResultCode member is 80131500 in the first two records, and 80131534 in the third record. A quick use of the !error <code> command looks up the descriptions:

     

    0:007> !error 80131500

    Error code: (HRESULT) 0x80131500 (2148734208) - <Unable to get error code text>

     

    0:007> !error 80131534

    Error code: (HRESULT) 0x80131534 (2148734260) - <Unable to get error code text>

     

    In this case, both aren‘t well-known error codes. This is common as API specific error codes aren’t in the OS error lookup routines.

     

    Here are some examples of known error codes, found by looking at a random selection of dumps. Some are quite common (80004003, 80004005 and 80070057) while others are quite rare:

     

    0:004> !error 80004003

    Error code: (HRESULT) 0x80004003 (2147500035) - Invalid pointer

     

    0:004> !error 80004005

    Error code: (HRESULT) 0x80004005 (2147500037) - Unspecified error

     

    0:005> !error 8000ffff

    Error code: (HRESULT) 0x8000ffff (2147549183) - Catastrophic failure

     

    0:004> !error 80070057

    Error code: (HRESULT) 0x80070057 (2147942487) - The parameter is incorrect.

     

    0:006> !error 80073db8

    Error code: (HRESULT) 0x80073db8 (2147958200) - Loading the state store failed.

     

    0:005> !error 800f1000

    Error code: (HRESULT) 0x800f1000 (2148470784) - No installed components were detected.

     

    0:006> !error 88985004

    Error code: (HRESULT) 0x88985004 (2291683332) - A font file exists but could not be opened due to access denied, sharing violation, or similar error.

     

    Original Call Stack

    Regardless of whether the error code is known or unknown, it is useful to determine the location of the issue by viewing the call stack.

     

    Symbol Pointers

    If the ExceptionForm member has a value of 0y01, the structure’s union represents a call stack.

     

    Unlike call stacks associated with threads, where the symbol pointers are placed throughout the stack next to local variables, these symbols pointers are packed tightly at the address specified in the StackTrace member. The dpS command is used to display the call stack.

    • It is important to include a limit (L) as the call stack is regularly longer than the default 10 rows displayed by dpS. The limit’s value is in the StackTraceWords member.
    • Note that capital S is used (dps vs dpS) because we want to omit the first column normally displayed by dps; the location of the symbol pointer is irrelevant.
    • If you aren‘t using the same bitness debugger as the target’s bitness, use ddS for StackTraceWordSize = 4, and dqS for StackTraceWordSize = 8.

     

    0:004> dt -a3 0180cf90 combase!_STOWED_EXCEPTION_INFORMATION_V1*

    [0] @ 0180cf90

    ---------------------------------------------

    0x070884a4

       +0x000 Header           : _STOWED_EXCEPTION_INFORMATION_HEADER

       +0x008 ResultCode       : 80131500

       +0x00c ExceptionForm    : 0y01

       +0x00c ThreadId         : 0y000000000000000000010100111100 (0x53c)

       +0x010 ExceptionAddress : 0x7721ea23 Void

       +0x014 StackTraceWordSize : 4

       +0x018 StackTraceWords  : 5

       +0x01c StackTrace       : 0x06f48418 Void

       +0x010 ErrorText        : 0x7721ea23  "?????"

    ...

     

    0:007> dpS 0x06f48418 L5

    7723f217 combase!RoOriginateLanguageException+0x3b

    72e29bfd clr!SetupErrorInfo+0x1e1

    72ef27e1 clr!MarshalNative::GetHRForException_WinRT+0x7d

    71981170 Windows_UI_Xaml_ni+0x291170

    72b02a36 clr!COMToCLRDispatchHelper+0x28

     

    Unicode String Pointer

    If the ExceptionForm member has a value of 0y10, the structure’s union represents an error message.

     

    The call stack is (hopefully) contained within the Unicode string pointed at by the ErrorText member. As the text is defined by the caller, the existence of a call stack text isn’t guaranteed.

     

    0:005> dt –a1 13f117e0 combase!_STOWED_EXCEPTION_INFORMATION_V1*

    [0] @ 13f117e0

    ---------------------------------------------

    0x0471f3c0

       +0x000 Header           : _STOWED_EXCEPTION_INFORMATION_HEADER

       +0x008 ResultCode       : 8000ffff

       +0x00c ExceptionForm    : 0y10

       +0x00c ThreadId         : 0y000000000000000000010101110100 (0x574)

       +0x010 ExceptionAddress : 0x0de38f7c Void

       +0x014 StackTraceWordSize : 0

       +0x018 StackTraceWords  : 0

       +0x01c StackTrace       : (null)

       +0x010 ErrorText        : 0x0de38f7c  "System.Exception..   at Windows.UI.Xaml.VisualStateManager.GoToState(Control control, String stateName, Boolean useTransitions)..   at MyBadApp.Common.LayoutAwarePage.InvalidateVisualState()..   at MyBadApp.Common.LayoutAwarePage.WindowSizeChanged(Object sender, WindowSizeChangedEventArgs e)"

     

    CLR - Last Exception Object

    Sometimes, the call stack retrieved from the record isn’t that useful. It may just be the call stack leading up to RoOriginateLanguageException function call, or it just might not relate to any of the code that the application author has written. In these cases, the CLR provides one more chance to understand the issue.

     

    When the CLR throws an exception on a managed thread, the address of the exception object is kept in an (internal) per-thread variable. This address is what the !sos.pe (print exception) command reads to display the CLR Last Exception of a thread.

     

    Note, if you use the Windows 8.1 SDK version of the Debugging Tools for Windows, SOS will be automatically loaded for you, including the download of any required DLLs. As such, it is highly suggested that you use the Windows 8.1 version.

     

    Example #1

    Looking at this example, we can see that there is a single record with an "Invalid pointer" error.

     

    0:006> .exr -1

    ExceptionAddress: 00007ffb87c46960 (twinapi_appcore!Microsoft::WRL::ComPtr<Windows::ApplicationModel::Core::UnhandledErrorDetectedEventArgs>::{dtor})

       ExceptionCode: c000027b

      ExceptionFlags: 00000001

    NumberParameters: 2

       Parameter[0]: 0000003fbc80c8a0

       Parameter[1]: 0000000000000001

     

    0:006> dt -a1 0000003fbc80c8a0 combase!_STOWED_EXCEPTION_INFORMATION_V1*

    [0] @ 0000003f`bc80c8a0

    ---------------------------------------------

    0x0000003f`bfc3c5b8

       +0x000 Header           : _STOWED_EXCEPTION_INFORMATION_HEADER

       +0x008 ResultCode       : 80004003

       +0x00c ExceptionForm    : 0y01

       +0x00c ThreadId         : 0y000000000000000000100111001000 (0x9c8)

       +0x010 ExceptionAddress : 0x00007ffb`981e1f1c Void

       +0x018 StackTraceWordSize : 8

       +0x01c StackTraceWords  : 0x18

       +0x020 StackTrace       : 0x0000003f`bd7ac9c0 Void

       +0x010 ErrorText        : 0x00007ffb`981e1f1c  "???"

     

    0:006> !error 80004003

    Error code: (HRESULT) 0x80004003 (2147500035) - Invalid pointer

     

    This is a common call stack. A CLR exception is being marshaling to the unhandled error reporting sub-system of WinRT.

     

    0:006> dpS 0x0000003f`bd7ac9c0 L18

    00007ffb`98238d27 combase!RoOriginateLanguageException+0x57

    00007ffb`71e0f926 mscorlib_ni!DomainNeutralILStubClass.IL_STUB_PInvoke(Int32, System.String, IntPtr)+0xe6

    00007ffb`71ff7084 mscorlib_ni!System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeMarshal.RoOriginateLanguageException(Int32, System.String, IntPtr)+0x44

    00007ffb`71ff6b8d mscorlib_ni!System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeMarshal.ReportUnhandledError(System.Exception)+0x12d

    00007ffb`885042f4 System_Runtime_WindowsRuntime_ni!System.Threading.WinRTSynchronizationContext+Invoker.InvokeCore()+0x73e04

    00007ffb`7ee6b915 clr!ExceptionTracker::CallHandler+0xc5

    00007ffb`7ee6b80b clr!ExceptionTracker::CallCatchHandler+0x7f

    00007ffb`7ee6b728 clr!ProcessCLRException+0x2e6

    00007ffb`9a30a7fd ntdll!RtlpExecuteHandlerForUnwind+0xd

    00007ffb`9a2b36ba ntdll!RtlUnwindEx+0x366

    00007ffb`7ee6d1c0 clr!ClrUnwindEx+0x40

    00007ffb`7ee6d174 clr!ProcessCLRException+0x2b2

    00007ffb`9a30a77d ntdll!RtlpExecuteHandlerForException+0xd

    00007ffb`9a2b29fb ntdll!RtlDispatchException+0x19b

    00007ffb`9a2b2668 ntdll!RtlRaiseException+0xf0

    00007ffb`976c8384 KERNELBASE!RaiseException+0x68

     

    There is a CLR Last Exception object and the exception code of it matches the record’s code:

     

    0:006> !sos.pe

    Exception object: 0000003fa2be4830

    Exception type:   System.NullReferenceException

    Message:          Object reference not set to an instance of an object.

    InnerException:   <none>

    StackTrace (generated):

        SP               IP               Function

        0000003FBC80D190 00007FFB1F72FC18 MyBadApp!MyBadApp.Utilities.Authentication.GetAliasFromSecurityToken()+0x18

        0000003FBC80D1D0 00007FFB1F72FAC2 MyBadApp! MyBadApp.MainPage.MainPage_AuthenticateUserCompleted(System.Object, System.EventArgs)+0x82

        0000003FBC80D210 00007FFB1F72F5E5 MyBadApp! MyBadApp.MainPage+<AuthenticateUser_Async>d__0.MoveNext()+0x305

        0000003FBC80EE60 00007FFB724F0B31 mscorlib_ni!System.Runtime.CompilerServices.AsyncMethodBuilderCore.<ThrowAsync>b__4(System.Object)+0x4d61d1

        0000003FBC80EE90 00007FFB88490523 System_Runtime_WindowsRuntime_ni!System.Threading.WinRTSynchronizationContext+Invoker.InvokeCore()+0x33

     

    StackTraceString: <none>

    HResult: 80004003

     

    In this case, you can surmise that the System.NullReferenceException exception was thrown within the MyBadApp!MyBadApp.Utilities.Authentication.GetAliasFromSecurityToken() function, and that it was unhandled.

     

    Extraction of the CLR Last Exception object can also sometimes be done in Visual Studio. When you do a Debug with Managed Only on the dump file, the Locals window sometimes contains a pseudo variable called $exception that represents the exception.

     

    VisualStudio-Locals

     

    The Text Visualizer of the StackTrace member allows you to see the call stack.

     

    TextVisualizer

     

    Example #2

    Looking at another example, we can see that again there is a single record, this time with an "Unspecified error" exception code.

     

    0:004> .exr -1

    ExceptionAddress: 73034fec (Windows_UI_Xaml!DirectUI::ErrorHelper::ProcessUnhandledError+0x000000b8)

       ExceptionCode: c000027b

      ExceptionFlags: 00000001

    NumberParameters: 2

       Parameter[0]: 0bdaf240

       Parameter[1]: 00000001

     

    0:004> dt -a1 0bdaf240 combase!PSTOWED_EXCEPTION_INFORMATION_V1

    [0] @ 0bdaf240

    ---------------------------------------------

    0x0af64034

       +0x000 Header           : _STOWED_EXCEPTION_INFORMATION_HEADER

       +0x008 ResultCode       : 80004005

       +0x00c ExceptionForm    : 0y01

       +0x00c ThreadId         : 0y000000000000000000010010011110 (0x49e)

       +0x010 ExceptionAddress : (null)

       +0x014 StackTraceWordSize : 4

       +0x018 StackTraceWords  : 5

       +0x01c StackTrace       : 0x0af6302c Void

       +0x010 ErrorText        : (null)

     

    0:006> !error 80004005

    Error code: (HRESULT) 0x80004005 (2147500037) - Unspecified error

     

    The call stack of the record suggests that this is associated with GetNavigationState:

     

    0:004> dpS 0x0af6302c L5

    72ec4e7d Windows_UI_Xaml!DirectUI::NavigationHistory::WritePageStackEntryToString+0x1f7fde

    72ec4ef0 Windows_UI_Xaml!DirectUI::NavigationHistory::GetNavigationState+0x1f7ddf

    72ccd0fa Windows_UI_Xaml!DirectUI::Frame::GetNavigationStateImpl+0x3a

    72cccced Windows_UI_Xaml!DirectUI::FrameGenerated::GetNavigationState+0x2f

    737d00eb Windows_UI_Xaml_ni+0x2400eb

     

    But the CLR Last Exception object doesn’t have the same exception code as the record:

     

    0:004> !sos.pe

    Exception object: 02cb3cb8

    Exception type:   <Unknown>

    Message:          <Invalid Object>

    InnerException:   System.Runtime.InteropServices.COMException, Use !PrintException e2a09bc6 to see more.

    StackTrace (generated):

        SP       IP       Function

        052DF6C0 07141094 MyBadApp!UNKNOWN+0x544

        052DF8A4 73E0D17A mscorlib_ni!System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(System.Threading.Tasks.Task)+0x5e

        052DF8B4 73E0D115 mscorlib_ni!System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(System.Threading.Tasks.Task)+0x35

        052DF8C0 071409DB MyBadApp!UNKNOWN+0xb3

        052DF8CC 7458458F mscorlib_ni!System.Runtime.CompilerServices.AsyncMethodBuilderCore.<ThrowAsync>b__4(System.Object)+0x33

        052DF8D4 6F9EF994 System_Runtime_WindowsRuntime_ni!System.Threading.WinRTSynchronizationContext+Invoker.InvokeCore()+0x24

     

    StackTraceString: <none>

    HResult: 80131500

     

    0:006> !error 80131500

    Error code: (HRESULT) 0x80131500 (2148734208) - <Unable to get error code text>

     

    It does however have a nested CLR Exception object that does have the same exception code as the record. It too has a call stack that indicates GetNavigationState is having an issue.

     

    0:004> !PrintException /d 02caf968

    Exception object: 02caf968

    Exception type:   System.Runtime.InteropServices.COMException

    Message:          <Invalid Object>

    InnerException:   <none>

    StackTrace (generated):

        SP       IP       Function

        00000000 00000001 Windows_UI_Xaml_ni!Windows.UI.Xaml.Controls.Frame.GetNavigationState()+0x2

        052DF778 071411B5 MyBadApp!UNKNOWN+0x1d

        052DF788 07140BF3 MyBadApp!UNKNOWN+0xa3

     

    StackTraceString: <none>

    HResult: 80004005

     

    Summary

    The asynchronous and projected nature of Windows Store applications makes them significantly harder to debug than desktop applications. Knowing the error code and call stack is just the first step in understanding the root cause of a crash in a Store application. Hopefully this blog post has made those first steps easier to undertake, and that those first steps have pointed you in the right direction.

     

    The solutions to some of the more common issues have been talked about on episodes of Channel 9 Defrag Tools. These episodes show the code changes required to avoid the hang or crash:

Page 1 of 1 (1 items)