BadImageFormatException or TypeInitializationException when using mixed mode VC++ dlls in managed servicesapplications

Problem

When using mixed mode VC++ dlls in your managed services\applications, you may encounter exceptions like BadImageFormatException or TypeInitializationException when your module is loaded in non-default domain.

Rootcause:

When you link your module to CRT, the CRT has to do some per-process initialization.

Since CRT is a process-wide entity, per-process initialization is done in the default domain. There is no workaround for that other than stopping using the CRT (/clr:safe) or loading the module in default domain. Also, Constructors of unmanaged globals are executed in the default domain. If your module is loaded in non-default domain [for example, hosting in ASP.net application or WCF service], the initialization code that runs in default domain, could encounter exceptions like BadImageFormatException.

Workaround:

Load the mixed mode C++ modules in default domain.

OR use/ clr:safe to stop using CRT

 

More Information

If you are debugging your application or service in windbg.exe and enable break on CLR exceptions as below

enable break on CLR exceptions

 

0:00> sxe clr

 

Issue 'go' command

0:00> g

 

At the point of exception, you will see a call stack similar to this

 0:015> k 200
ChildEBP RetAddr
076ccfd8 6a43a99c KERNEL32!RaiseException+0x58
076cd038 6a499ec4 mscorwks!RaiseTheExceptionInternalOnly+0x2a8
076cd070 6a584e84 mscorwks!UnwindAndContinueRethrowHelperAfterCatch+0x70
076cd0c4 6a5851b1 mscorwks!IJWNOADThunk::FindThunkTarget+0x179
076cd0cc 6a3d1ae1 mscorwks!IJWNOADThunkJumpTargetHelper+0xb
076cd0ec 6a5eecb9 mscorwks!IJWNOADThunkJumpTarget+0x48
076cd140 6a5f2e0e mscorwks!ExecuteInAppDomainHelper+0x5c
076cd260 6a3d1d8b mscorwks!CorHost2::ExecuteInAppDomain+0x211
076cd290 000da056 mscorwks!PInvokeCalliReturnFromCall
076cd2b4 011c46f6 CLRStub[StubLinkStub]@da056
076cd310 0074c81c msvcm80!<CrtImplementationDetails>::DoCallBackInDefaultDomain+0x86
WARNING: Frame IP not in any known module. Following frames may be wrong.
076cd328 012758f5 0x74c81c
076cd348 011cc463 CLRStub[StubLinkStub]@12758f5
*** ERROR: Module load completed but symbols could not be loaded for C:\Windows\assembly\GAC_32\sbclient\6.1.0.0__371d4a7d6f5d7853\dotnetapi.dll
076cd370 011c3f8f dotnetapi!<Module>.<CrtImplementationDetails>.LanguageSupport.InitializeDefaultAppDomain(<CrtImplementationDetails>.LanguageSupport*)+0x1b
076cd3d8 011c3d81 dotnetapi!<Module>.<CrtImplementationDetails>.LanguageSupport._Initialize(<CrtImplementationDetails>.LanguageSupport*)+0x147
076cd40c 011c3bd0 dotnetapi!<Module>.<CrtImplementationDetails>.LanguageSupport.Initialize(<CrtImplementationDetails>.LanguageSupport*)+0x61
076cd438 6a3d1b4c dotnetapi!<Module>..cctor()+0x20
076cd448 6a3e21f9 mscorwks!CallDescrWorker+0x33
076cd4c8 6a3e285f mscorwks!CallDescrWorkerWithHandler+0xa3
076cd4e8 6a3e28a0 mscorwks!DispatchCallBody+0x1e
076cd54c 6a3e2911 mscorwks!DispatchCallDebuggerWrapper+0x3d
076cd580 6a3f5b47 mscorwks!DispatchCallNoEH+0x51
076cd624 6a3f5a2a mscorwks!MethodTable::RunClassInitEx+0x107
076cdb14 6a4c5d90 mscorwks!MethodTable::DoRunClassInitThrowing+0x526
076cdb60 6a437a1b mscorwks!DomainFile::Activate+0x226
076cdb6c 6a41c4af mscorwks!DomainFile::DoIncrementalLoad+0xb4
076cdbf0 6a41c3b6 mscorwks!AppDomain::TryIncrementalLoad+0x97
076cdc40 6a437ad8 mscorwks!AppDomain::LoadDomainFile+0x19d
076cdc7c 6a41c7a3 mscorwks!AppDomain::LoadDomainFile+0x7b
076cdc94 6a416bed mscorwks!DomainFile::EnsureLoadLevel+0x1a
076cdd10 6a437735 mscorwks!DomainFile::TryEnsureActive+0x71
076cde00 6a4377cb mscorwks!DomainFile::PropagateActivationInAppDomain+0x167

Using the CLR debugger extension sos.dll from the framework directory, examine the exception object [step-by-step below]

command to load the debugger extension

0:015> .load c:\Windows\Microsoft.NET\Framework\v2.0.50727\sos.dll

command to Dump all the objects on the stack using the following command

0:015> !dso
OS Thread Id: 0xc24 (15)
ESP/REG Object Name
07a1d138 029f6e4c System.BadImageFormatException
07a1d180 029f6e4c System.BadImageFormatException
07a1d2c0 0295f0a4 System.Threading.ExecutionContext
07a1d720 0296d864 <CrtImplementationDetails>.Handle<System::Object ^>
07a1ef7c 0296d854 WcfService.Service1
07a1ef88 0295f4c0 System.ServiceModel.Security.SecurityVerifiedMessage
07a1ef8c 0296d854 WcfService.Service1
07a1ef90 02856630 System.ServiceModel.EndpointAddress
07a1efa8 02843d7c System.ServiceModel.Dispatcher.InstanceBehavior
07a1efb4 0295f4c0 System.ServiceModel.Security.SecurityVerifiedMessage
07a1efb8 0296cd94 System.ServiceModel.InstanceContext
07a1efbc 0295f4c0 System.ServiceModel.Security.SecurityVerifiedMessage
07a1efc8 0295f4c0 System.ServiceModel.Security.SecurityVerifiedMessage
07a1efcc 0296ce04 System.Object
07a1efe8 02856630 System.ServiceModel.EndpointAddress
07a1efec 02843cec System.ServiceModel.Dispatcher.ImmutableDispatchRuntime
07a1f004 02843cec System.ServiceModel.Dispatcher.ImmutableDispatchRuntime
07a1f01c 02848d6c System.ServiceModel.Dispatcher.MessageRpcProcessor
07a1f020 02856630 System.ServiceModel.EndpointAddress

command to dump the contents of BadImageFormatException. Note we copied the address from the list of objects on the stack above

0:015> !do 029f6e4c

Name: System.BadImageFormatException

MethodTable: 690198a0

EEClass: 68e568c4

Size: 80(0x50) bytes

GC Generation: 0

 (C:\Windows\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)

Fields:

      MT Field Offset Type VT Attr Value Name

69040a00 40000b5 4 System.String 0 instance 02ad6920 _className

6903fe74 40000b6 8 ...ection.MethodBase 0 instance 00000000 _exceptionMethod

69040a00 40000b7 c System.String 0 instance 00000000 _exceptionMethodString

69040a00 40000b8 10 System.String 0 instance 02ad6a74 _message

6903a35c 40000b9 14 ...tions.IDictionary 0 instance 00000000 _data

69040b94 40000ba 18 System.Exception 0 instance 00000000 _innerException

69040a00 40000bb 1c System.String 0 instance 00000000 _helpURL

6904061c 40000bc 20 System.Object 0 instance 00000000 _stackTrace

69040a00 40000bd 24 System.String 0 instance 00000000 _stackTraceString

69040a00 40000be 28 System.String 0 instance 02901198 _remoteStackTraceString

69042c4c 40000bf 34 System.Int32 1 instance 0 _remoteStackIndex

6904061c 40000c0 2c System.Object 0 instance 00000000 _dynamicMethods

69042c4c 40000c1 38 System.Int32 1 instance -2146234344 _HResult

69040a00 40000c2 30 System.String 0 instance 00000000 _source

690432c8 40000c3 3c System.IntPtr 1 instance 0 _xptrs

69042c4c 40000c4 40 System.Int32 1 instance 0 _xcode

69040a00 4000209 44 System.String 0 instance 02ad6d84 _fileName

69040a00 400020a 48 System.String 0 instance 02901198 _fusionLog

Dump the contents of the exception's 'message'

 

0:015> !do 02ad6a74

Name: System.String

MethodTable: 69040a00

EEClass: 68dfd64c

Size: 282(0x11a) bytes

GC Generation: 0

 (C:\Windows\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)

String: Could not load file or assembly 'abcde.dll' or one of its dependencies. The module was expected to contain an assembly manifest.

Fields:

      MT Field Offset Type VT Attr Value Name

69042c4c 4000096 4 System.Int32 1 instance 133 m_arrayLength

69042c4c 4000097 8 System.Int32 1 instance 132 m_stringLength

690416e0 4000098 c System.Char 1 instance 43 m_firstChar

69040a00 4000099 10 System.String 0 shared static Empty

    >> Domain:Value 007a6f08:02901198 053d1f00:02901198 <<

69041630 400009a 14 System.Char[] 0 shared static WhitespaceChars

    >> Domain:Value 007a6f08:02901760 053d1f00:02932d40 <<

Note If you continue to run the application, by issuing a 'g' , you will notice exceptions like

<CrtImplementationDetails>.ModuleLoadExceptionHandlerException

 System.TypeInitializationException

Note that if you are debugging in Visual Studio, you will see TypeInitialization exception, with the message "The type initializer for '<Module>' threw an exception."

So, why did it cause the exception?

Examine the managed threads

 

0:015> !Threads
ThreadCount: 10
UnstartedThread: 0
BackgroundThread: 7
PendingThread: 0
DeadThread: 2
Hosted Runtime: no
PreEmptive GC Alloc Lock
ID OSID ThreadOBJ State GC Context Domain Count APT Exception
0 1 774 0080ada0 6020 Enabled 029fa3cc:029fc39c 00806f10 0 STA
2 2 fe4 0083f730 b220 Enabled 0292e810:029307f4 00806f10 0 MTA (Finalizer)
8 3 d6c 0502aba8 1220 Enabled 00000000:00000000 00806f10 0 Ukn
9 4 12c8 0503fe50 80a220 Enabled 00000000:00000000 00806f10 0 MTA (Threadpool Completion Port)
11 5 1554 0504a7b8 180b220 Enabled 029fc4ec:029fe39c 00806f10 0 MTA (Threadpool Worker)
12 6 14dc 0504a3b0 a80b220 Enabled 029f8440:029fa39c 0502b870 0 MTA (Threadpool Completion Port)
XXXX 7 0 05063578 8801820 Enabled 00000000:00000000 00806f10 0 Ukn (Threadpool Completion Port)
XXXX 8 0 05081528 8801820 Enabled 00000000:00000000 00806f10 0 Ukn (Threadpool Completion Port)
15 9 c24 05070230 880b220 Enabled 02a0dda4:02a0e3b4 0502b870 4 MTA (Threadpool Completion Port) System.TypeInitializationException (02a0db04)
  10 a 161c 05091900 880b220 Enabled 02a0474c:02a063b4 00806f10 0 MTA (Threadpool Completion Port)

The current thread of execution is Thread 15, which is in Application domain 0502b870

This is not the default domain. You can verify by issuing the command to list the domains i.e, !dumpdomain

 

!dumpdomain

0:015> !dumpdomain
--------------------------------------
System Domain: 6d97d058
LowFrequencyHeap: 6d97d07c
HighFrequencyHeap: 6d97d0c8
StubHeap: 6d97d114
Stage: OPEN
Name: None
--------------------------------------
Shared Domain: 6d97c9a8
LowFrequencyHeap: 6d97c9cc
HighFrequencyHeap: 6d97ca18
StubHeap: 6d97ca64

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

Domain 1: 00806f10============> Default Domain
LowFrequencyHeap: 00806f34
HighFrequencyHeap: 00806f80
StubHeap: 00806fcc
Stage: OPEN
SecurityDescriptor: 00807c68
Name: WcfSvcHost.exe

--------------------------------------
Domain 2: 0502b870
LowFrequencyHeap: 0502b894
HighFrequencyHeap: 0502b8e0
StubHeap: 0502b92c
Stage: OPEN
SecurityDescriptor: 008adf18
Name: WcfService.dll.config