Debugging a Windows 8.1 Store App Crash Dump

Debugging a Windows 8.1 Store App Crash Dump

Rate This
  • Comments 0

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:

Leave a Comment
  • Please add 2 and 3 and type the answer here:
  • Post