Dziś powiemy sobie na temat (chyba) najbardziej zaawansowanego narzędzia służącego do debuggowania naszego kodu na produkcji. WinDbg, bo o nim będzie mowa, to część pakietu Debugging Tools for Windows.
Do celów przykładowych posłużymy się aplikacją z poprzedniego wpisu o mDbg.

WinDbg

Tak jak już było wspomniane wyżej WinDbg to część większego pakietu Debugging Tools for Windows i jest dostępny w dwóch wersjach 32- i 64-bitowej. Obowiązkowe narzędzie dla kogoś kto chce na poważnie zajmować się debuggowaniem. Zatem jak zacząć? Po uruchomieniu WinDbg nie sprawia dobrego wrażenia – surowy interface nie zachęca do pracy z nim.
windbg
Pierwsze od czego powinniśmy zacząć pracę z tym narzędziem to skonfigurowanie symboli. Aby to zrobić należy wybrać opcję File| Symbol File Path i wpisać: SRV*c:\websymbols*http://msdl.microsoft.com/download/symbols. Uruchamiamy naszą aplikację pod kontrolą WinDbg. Różne są ustawienia aplikacji. Ja otwieram standardowo następujące okna: disassembly, calls, command, registers.
Aby móc debuggować aplikacji napisane w .NET musimy załadować specjalny dodatek sos (Son of Strike). Rozszerza on możliwości WinDbg o polecenia właściwe dla .NET (np. przeglądanie zarządzanego stosu itp.). Robimy to poleceniem .load <ścieżka do katalogu z .NET frameworkiem>\sos.dll lub też za pomocą .loadby sos np. .loadby sos clr.  Ja pozwoliłem aplikacji uruchomić się, aby załadowane zostały wszystkie dll’ki. Następnie CTRL-Pause Break przenosi nas do WinDbg a za pomocą ostatniego polecenia załadujemy rozszerzenie sos.
Mając załadowanie rozszerzenie sos, możemy przystąpić do działania. Wszystkie polecenia będące rozszerzeniem wykonujemy poprzedzając je znakiem ! (wykrzyknika) np. !EEheap – zwróci zawartość zarządzanego stosu, !clrstack wypisze zarządzany stos.
Jak znaleźć przyczynę błędu? Zobaczmy gdzie znajduje się nasza aplikacja obecnie. Wprowadzamy polecenie !dumpstack –EE i nie otrzymujemy nic interesującego. No tak, mamy wiele wątków w aplikacji i ten w którym aktualnie jesteśmy zatrzymani niekoniecznie jest wątkiem .NET. Szybkie podpatrzenie co zwróci nam polecenie !threads i już wiemy, że musimy przełączyć się na wątek 0 lub 2. ~0s i jesteśmy w pierwszym z nich. Ponownie !dumpstack i bingo. Widzimy tam wywołania takie jak ReadLine. To jest to – nasza aplikacja czeka przecież na naszą reakcję wprowadzenie danych z klawiatury.
dumpstack
Teraz wystarczy zrzucić IL’a wykonując polecenie !DumpIL 001537f0 (wartość z 4 kolumny ostatniej linii). I widzimy kod odpowiedzialny za obliczenia.
il
Co w nim się dzieje? IL_0000 mamy wywołanie ReadLine, na który się właśnie zatrzymaliśmy. Potem mamy pobranie zawartości wartości ze stosu i przechowanie jej w zmiennej lokalnej pod indeksem 0, potem wrzucenie tej samej zmiennej na stos i wywołanie IsNullOrWhiteSpace. Jeśli wprowadzono pusty ciąg znaków kończymy przetwarzanie. w przeciwnym przypadku wrzucamy na stos tę samą zmienną oraz liczbę 515 i wołamy <Int32.Parse. Zobaczmy na dostępne definicje metody Int32.Parse. Mam ona cztery przeciążenia w tym 2, które biorą dwa parametry (dwa wrzucenia na stos). Wrzucamy na stos prostą wartość więc wywołanie z IFormatprovider odpada. Zobaczmy co kryje się w NumberStyles. Jest to enum, tak więc jego wartość będzie konwertowana na liczbę. Musimy jeszcze dowiedzieć się jakiemu elementowi odpowiada wartość 515. Krótki rzut oka na IlSpy’a i wszystko jasne!
ilspy
WinDbg to potężne narzędzie a w tym wpisie nie wymieniłem nawet 5% jego możliwości. Zachęcam do dokładniejszego przyjrzenia się mu np. na stronie windbg.info jest tam całkiem obszerny pdf – WinDbg. From A to Z!