WinDbg / SOS / PSSCOR2 : Failed to load data access DLL (mscordacwks)
Ceux d'entre nous qui analysent des dumps d'applications .NET (notamment ceux créés via WER après un crash) en dehors de l'environnement initial ont probablement tous été confrontés au moins une fois au message suivant, à la saisie d'une commande SOS / PSSCOR :
Failed to load data access DLL, 0x80004005
Verify that 1) you have a recent build of the debugger (6.2.14 or newer)
2) the file mscordacwks.dll that matches your version of mscorwks.dll is
in the version directory
3) or, if you are debugging a dump file, verify that the file
mscordacwks_<arch>_<arch>_<version>.dll is on your symbol path.
4) you are debugging on the same architecture as the dump file.
For example, an IA64 dump file must be debugged on an IA64
machine.
You can also run the debugger command .cordll to control the debugger's
load of mscordacwks.dll. .cordll -ve -u -l will do a verbose reload.
If that succeeds, the SOS command should work on retry.
If you are debugging a minidump, you need to make sure that your executable
path is pointing to mscorwks.dll as well.
Celà se produit quand la version de .NET qui exécutait l'application pour laquelle le dump a été généré n'est pas exactement la même que sur la machine où ce dump est analysé, et que les serveurs de symboles publics de Microsoft n'ont pas pu délivrer automatiquement la version demandée.
Une fois que nous nous sommes assurés des points 1 et 4, le plus simple reste encore de récupérer la version de mscordacwks.dll de la machine ayant généré le dump, avant que l'installation de .NET ne soit mise à jour par un éventuel patch : mscordacwks.dll est livrée via les redistribuables .NET, et donc potentiellement mise à jour par les Service Packs et autres patches.
Je n'ai pas connaissance d'un dépôt public des différentes versions de mscordacwks.dll chez Microsoft : si les serveurs de symboles habituels (http://referencesource.microsoft.com/symbols et http://msdl.microsoft.com/download/symbols) ne fournissent pas ces fichiers, je ne vois pas d'autre solution que celle que je décris ci-dessous.
Où trouver le fichier sur la machine d'où provient le dump ?
Ce fichier se trouve dans le répertoire d'installation de .NET soit par exemple, pour .NET 2.0, "C:\Windows\Microsoft.NET\Framework\v2.0.50727" ou "C:\Windows\Microsoft.NET\Framework64\v2.0.50727".
En cas de doute sur l'architecture et/ou la version de .NET sous laquelle s'exécutait l'application et qu'il vous sera difficile de demander les fichiers après avoir obtenu le dump, faites vous livrer l'ensemble des versions disponibles. Par exemple :
- .NET 2.0 x86 : Framework\v2.0.50727\mscordacwks.dll
- .NET 2.0 x64 : Framework64\v2.0.50727\mscordacwks.dll
- .NET 4.0 x86 : Framework\v4.0.30319\mscordacwks.dll
- .NET 4.0 x64 : Framework64\v4.0.30319\mscordacwks.dll
Comment savoir où mettre ce fichier ?
En laissant de côté l'utilisation de ".cordll -lp Path" (afin de ne plus être embêté par la suite pour la même version de mscorwks.dll), le mieux est probablement d'utiliser la commande donnée dans le message initial : ".cordll -ve -u -l", en l'agrémentant de la commande "!sym noisy" afin d'obtenir plus de détails.
0:000> !sym noisy; .cordll -ve -u -l
noisy mode - symbol prompts on
CLR DLL status: No load attempts
Une fois cette commande exécutée, ré-émettons notre commande initiale.
Le message sera alors plus verbeux et contiendra des informations de ce genre :
0:000> !pe
CLRDLL: Unable to get version info for 'c:\Symbols\mscorwks.dll\4BE902C7590000\mscordacwks.dll', Win32 error 0n87
SYMSRV: c:\Symbols\mscordacwks_x86_x86_2.0.50727.3615.dll\4BE902C7590000\mscordacwks_x86_x86_2.0.50727.3615.dll not found
SYMSRV: http://referencesource.microsoft.com/symbols/mscordacwks_x86_x86_2.0.50727.3615.dll/4BE902C7590000/mscordacwks_x86_x86_2.0.50727.3615.dll not found
SYMSRV: c:\Symbols\mscordacwks_x86_x86_2.0.50727.3615.dll\4BE902C7590000\mscordacwks_x86_x86_2.0.50727.3615.dll not found
SYMSRV: http://msdl.microsoft.com/download/symbols/mscordacwks_x86_x86_2.0.50727.3615.dll/4BE902C7590000/mscordacwks_x86_x86_2.0.50727.3615.dll not found
CLRDLL: Unable to find mscordacwks_x86_x86_2.0.50727.3615.dll by mscorwks search
CLRDLL: Unable to find 'mscordacwks_x86_x86_2.0.50727.3615.dll' on the path
CLRDLL: ERROR: Unable to load DLL mscordacwks_x86_x86_2.0.50727.3615.dll, Win32 error 0n2
...
Nous avons donc apparemment le choix entre 2 chemins. Personnellement je préfère la version spécifiant explicitement l'architecture, et de toute façon je ne suis pas certains qu'utiliser l'autre soit vraiment une bonne idée.
Dans le cas présent, il ne nous reste donc "plus qu'à" prendre le fichier mscordacwks.dll issu du répertoire Framework\v2.0.50727 de la machine, le renommer en "mscordacwks_x86_x86_2.0.50727.3615.dll" et à le placer dans le répertoire "C:\Symbols\mscordacwks_x86_x86_2.0.50727.3615.dll\4BE902C7590000\", sans doute créé pour l'occasion.
Nous pouvons à présent ré-émettre la commande ".cordll -ve -u -l" (pour forcer une nouvelle tentative de chargement de la dll mscordacwks sans relancer la session de debug) puis la commande que nous voulions exécuter il y a 15 minutes.
Facile, non ? ;-)
Bien sûr s'il existe plus simple et/ou rapide, je suis preneur.
Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :