Update: I have since turned this into a WinDbg extension.
Let us say that you for some reason have made a 64-bit dump of a 32-bit .NET process (possibly by mistake), and you need to investigate it. It used to be that you could just load it into the 32-bit version of WinDbg and use !wow64ext.sw to switch into the 32-bit view of the process, and then SOS would work fine. However if you try this with .NET 4.5/4.5.1 then this is the result:
SOS does not support the current target architecture.
So… what can one do then? Attempting to remove some checks from windbg and sos perhaps?
It turns out that this is possible. The following instructions works with windbg from debugging tools for Windows 8.1 and Windows 10.
First open the dump in a windbg instance, shift it to the 32-bit view with !wow64ext.sw, load sos and then attempt to run some sos command. You will get the error message above.
Then start another windbg and attach that to the first instance. First we need to make SoS use the effective architecture instead of the executing architecture. The address we need to patch has changed a bit between versions of sos.dll (probably due to compiler optimizations), so do an assembly listing of sos!ArchQuery with the uf command:
0:005> uf sos!ArchQuery sos!ArchQuery: 0473c5b0 55 push ebp 0473c5b1 8bec mov ebp,esp 0473c5b3 51 push ecx 0473c5b4 a1907f7a04 mov eax,dword ptr [sos!g_ExtControl (047a7f90)] 0473c5b9 56 push esi 0473c5ba 8b08 mov ecx,dword ptr [eax] 0473c5bc 8d55fc lea edx,[ebp-4] 0473c5bf 52 push edx 0473c5c0 50 push eax 0473c5c1 33f6 xor esi,esi ; IDebugControl5 90 -> BC: IDebugControl::GetEffectiveProcessorType ; 0x0473c5c3+2 - 0x0473c5b0 = 0x15. sos!ArchQuery+0x15 0473c5c3 ff9190000000 call dword ptr [ecx+90h] ; IDebugControl::GetExecutingProcessorType dbgeng!DebugCreate+0x3c5f 0473c5c9 8b45fc mov eax,dword ptr [ebp-4] 0473c5cc 3d4c010000 cmp eax,14Ch 0473c5d1 750a jne sos!ArchQuery+0x2d (0473c5dd) Branch
Look for the bolded line. Then calculate the address of that plus 2 and subtract the first address listed, like I have done in the blue comment. Now you have the relative address from the start of sos!ArchQuery to patch (e.g. 0x15 in my case). Now you can in the future refere to that location in your sos.dll version as sos!ArchQuery + <addr>. We have to patch that from 0x90 (IDebugControl::GetExecutingProcessorType) to 0xBC (IDebugControl::GetEffectiveProcessorType):
eb sos!ArchQuery+0x15 0xBC
(replace 0x15 with the relative address you just calculated).
Now this makes some of the sos commands works, e.g. !threads and !dumpstack works now, but others such as !CLRStack does not. This can be fixed by patching the function dbgeng!X86MachineInfo::ConvertCanonContextToTarget. Make a listing of this:
dbgeng!X86MachineInfo::ConvertCanonContextToTarget: 693ceef8 8bff mov edi,edi 693ceefa 55 push ebp 693ceefb 8bec mov ebp,esp 693ceefd 53 push ebx 693ceefe 56 push esi 693ceeff 57 push edi 693cef00 8b7d0c mov edi,dword ptr [ebp+0Ch] 693cef03 33db xor ebx,ebx 693cef05 57 push edi 693cef06 53 push ebx 693cef07 ff7510 push dword ptr [ebp+10h] 693cef0a 8bf1 mov esi,ecx 693cef0c e8c5690d00 call dbgeng!memset (694a58d6) 693cef11 8b4608 mov eax,dword ptr [esi+8] 693cef14 83c40c add esp,0Ch 693cef17 81b8a800000001100000 cmp dword ptr [eax+0A8h],1001h 693cef21 7715 ja dbgeng!X86MachineInfo::ConvertCanonContextToTarget+0x40 (693cef38) dbgeng!X86MachineInfo::ConvertCanonContextToTarget+0x2b: 693cef23 81ffcc000000 cmp edi,0CCh 693cef29 7264 jb dbgeng!X86MachineInfo::ConvertCanonContextToTarget+0x97 (693cef8f)
We need to patch this check out (note that your windbg instance might have problems with non-x86 dumps after this). So just replace the conditional jump with two nops:
ew dbgeng!X86MachineInfo::ConvertCanonContextToTarget+0x29 0x9090
Again the 0x29 may be different in your version, it is the bolded address minus the start address. Also the value compared to is 0x1004 instead of 0x1001 in debugging tools for windows 10 (probably because it's an enum where members has been added).
Then just detach your second windbg instance from the first one and close it. After this every sos command I have tried seems to be working fine.