Wyjście Spis treści Poprzedni Następny
Autor:
©Iczelion |
©2008 mgr Jerzy Wałaszek I LO w Tarnowie |
|
|
Na tej lekcji będziemy kontynuować eksplorację funkcji uruchomieniowych zawartych w bibliotece Win32 API. W szczególności nauczymy się śledzić testowany proces.
Załaduj {ten przykład}
Jeśli już wcześniej korzystałeś z usług programu uruchomieniowego (debuggera), to powinieneś wiedzieć, co to jest śledzenie. Polega ono na tym, iż śledzony program zatrzymuje się po wykonaniu każdej instrukcji, co daje ci szansę sprawdzenia zawartości rejestrów oraz pamięci. Oficjalną nazwą śledzenia jest praca krokowa (single-stepping).
Sam mikroprocesor umożliwia tryb pracy krokowej. Ósmy bit rejestru znaczników jest nazywany znacznikiem pułapki (trap flag). Jeśli ten bitowy znacznik zostanie ustawiony, to mikroprocesor będzie pracował w trybie krokowym. Po każdej wykonanej instrukcji powstanie wyjątek uruchomieniowy (debug event). Po wygenerowaniu tego wyjątku bit pułapki jest automatycznie zerowany, co pozwala procedurze obsługi wyjątku wykonywać się w sposób ciągły.
Wykorzystując dostępne funkcje w bibliotece Win32 API możemy również nakazać wykonywanie testowanego procesu w trybie krokowym. Oto co należy wykonać w tym celu:
Plik DEBUG4.ASM
.386 .MODEL FLAT, STDCALL OPTION CASEMAP:NONE INCLUDE \masm32\include\windows.inc INCLUDE \masm32\include\kernel32.inc INCLUDE \masm32\include\comdlg32.inc INCLUDE \masm32\include\user32.inc INCLUDELIB \masm32\lib\kernel32.lib INCLUDELIB \masm32\lib\comdlg32.lib INCLUDELIB \masm32\lib\user32.lib .DATA AppName DB "Przykład uruchamiania nr 4", 0 ofn OPENFILENAME <> FilterString DB "Pliki wykonywalne", 0, "*.exe", 0, "Wszystkie pliki", 0, "*.*", 0, 0 ExitProc DB "Testowany proces kończy pracę", 0Dh, 0Ah, "Całkowita liczba wykonanych instrukcji : %lu", 0 TotalInstruction DD 0 .DATA? buffer DB 512 DUP(?) startinfo STARTUPINFO <> pi PROCESS_INFORMATION <> DBEvent DEBUG_EVENT <> ALIGN DWORD context CONTEXT <> .CODE start: mov ofn.lStructSize, SIZEOF ofn mov ofn.lpstrFilter, OFFSET FilterString mov ofn.lpstrFile, OFFSET buffer mov ofn.nMaxFile, 512 mov ofn.Flags, OFN_FILEMUSTEXIST OR \ OFN_PATHMUSTEXIST OR OFN_LONGNAMES OR\ OFN_EXPLORER OR OFN_HIDEREADONLY INVOKE GetOpenFileName, ADDR ofn .IF eax==TRUE INVOKE GetStartupInfo, ADDR startinfo INVOKE CreateProcess, ADDR buffer, NULL, NULL, NULL, FALSE, DEBUG_PROCESS + DEBUG_ONLY_THIS_PROCESS, NULL, NULL, ADDR startinfo, ADDR pi .WHILE TRUE INVOKE WaitForDebugEvent, ADDR DBEvent, INFINITE .IF DBEvent.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT INVOKE wsprintf, ADDR buffer, ADDR ExitProc, TotalInstruction INVOKE MessageBox, 0, ADDR buffer, ADDR AppName, MB_OK + MB_ICONINFORMATION .BREAK .ELSEIF DBEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT .IF DBEvent.u.Exception.pExceptionRecord.ExceptionCode==\ EXCEPTION_BREAKPOINT mov context.ContextFlags, CONTEXT_CONTROL INVOKE GetThreadContext, pi.hThread, ADDR context or context.regFlag, 100h INVOKE SetThreadContext, pi.hThread, ADDR context INVOKE ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_CONTINUE .CONTINUE .ELSEIF DBEvent.u.Exception.pExceptionRecord.ExceptionCode==\ EXCEPTION_SINGLE_STEP inc TotalInstruction INVOKE GetThreadContext, pi.hThread, ADDR context or context.regFlag, 100h INVOKE SetThreadContext, pi.hThread, ADDR context INVOKE ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_CONTINUE .CONTINUE .ENDIF .ENDIF INVOKE ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED .ENDW .ENDIF INVOKE CloseHandle, pi.hProcess INVOKE CloseHandle, pi.hThread INVOKE ExitProcess, 0 END start
Program wyświetla na ekranie okno dialogowe otwierania pliku. Gdy użytkownik wybierze plik wykonywalny, to zostanie on załadowany do pamięci i uruchomiony w trybie krokowym przy jednoczesnym zliczaniu wszystkich instrukcji, aż zakończy swoje działanie.
.ELSEIF DBEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT .IF DBEvent.u.Exception.pExceptionRecord.ExceptionCode==\ EXCEPTION_BREAKPOINT
Korzystamy z tej okazji do ustawienia testowanego procesu w tryb krokowy. Przypomnij sobie, iż system Windows wysyła powiadomienie EXCEPTION_BREAKPOINT tuż przed uruchomieniem pierwszej instrukcji w testowanym procesie.
mov context.ContextFlags, CONTEXT_CONTROL INVOKE GetThreadContext, pi.hThread, ADDR context
Wywołujemy funkcję GetThreadContext w celu wypełnienia struktury CONTEXT bieżącą zawartością rejestrów testowanego procesu. Szczególnie interesuje nas bieżąca zawartość rejestru znaczników mikroprocesora.
or context.regFlag, 100h
W obrazie rejestru znaczników ustawiamy bit pułapki (ósmy bit).
INVOKE SetThreadContext, pi.hThread, ADDR context INVOKE ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_CONTINUE .CONTINUE
Następnie wywołujemy SetThreadContext w celu zapisania zmienionych zawartości rejestrów w strukturze CONTEXT do kontekstu procesu i wywołujemy ContinueDebugEvent z ustawionym znacznikiem DBG_CONTINUE w celu wznowienia wykonania testowanego procesu.
.ELSEIF DBEvent.u.Exception.pExceptionRecord.ExceptionCode==\ EXCEPTION_SINGLE_STEP inc TotalInstruction
Gdy zostanie wykonana instrukcja w testowanym procesie, otrzymamy od systemu Windows powiadomienie EXCEPTION_DEBUG_EVENT. Musimy sprawdzić zawartość u.Exception.pExceptionRecord.ExceptionCode. Jeśli wynosi ona EXCEPTION_SINGLE_STEP, to dane zdarzenie uruchomieniowe powstało w wyniku pracy krokowej. W takim przypadku zwiększamy o jeden zawartość zmiennej TotalInstruction, ponieważ wiemy, iż w testowanym procesie została wykonana dokładnie jedna instrukcja.
INVOKE GetThreadContext, pi.hThread, ADDR context or context.regFlag, 100h INVOKE SetThreadContext, pi.hThread, ADDR context INVOKE ContinueDebugEvent, DBEvent.dwProcessId, DBEvent.dwThreadId, DBG_CONTINUE .CONTINUE
Ponieważ znacznik pułapki jest zerowany po wygenerowaniu wyjątku uruchomieniowego, musimy go ponownie ustawić, jeśli chcemy utrzymać w testowanym procesie tryb krokowy.
Uwaga: nie stosuj tego przykładu z dużym programem: śledzenie jest WOLNE. Możesz czekać nawet do 10 minut, zanim zakończy działanie testowany proces.
Autorem
kursu jest
Iczelion. Kurs
programowania Windows znalazł się na serwerze I LO w Tarnowie za pisemną
zgodą autora. |
I Liceum Ogólnokształcące |
Pytania proszę przesyłać na adres email: i-lo@eduinf.waw.pl
W artykułach serwisu są używane cookies. Jeśli nie chcesz ich otrzymywać,
zablokuj je w swojej przeglądarce.
Informacje dodatkowe