Popraw jakość kodu i zapobiegnij nieoczekiwanym rezultatom, ucząc się, jak używać debugera GNU do ujawniania niepożądanych błędów w kodzie.
Debugowanie jest niezbędną umiejętnością programistów i badaczy bezpieczeństwa. Dobra znajomość debugowania pozwala zrozumieć plik wykonywalny na niższym poziomie i wychwycić wszelkie ukryte błędy.
Debuger GNU, w skrócie GDB, to ponadczasowe narzędzie do debugowania, na którym programiści polegają od lat. Oto jak używać GDB w systemie Linux.
Przygotowanie przykładowych programów
Aby poznać funkcje GDB, będziesz potrzebować pliku wykonywalnego, z którym będziesz mógł eksperymentować. W celach demonstracyjnych uruchomisz GDB w programie do sprawdzania kluczy, raz z dostępnym kodem źródłowym i symbolami debugowania, raz bez kodzie źródłowym oraz na prostym, wielowątkowym programie wyświetlającym na ekranie komunikaty, zarówno napisane w C, jak i skompilowane przy użyciu GCC (GNU C Kompilator).
Możesz użyj dowolnego innego kompilatora C ale pamiętaj, aby nie rozebrać pliku binarnego.
Najprawdopodobniej będziesz uruchamiał GDB we własnych programach. Dlatego pamiętaj, aby skompilować je z rozszerzeniem -G flaga za pomocą gcc, aby włączyć symbole debugowania.
Bez obecnych symboli debugowania i przy mocno okrojonym pliku binarnym będziesz musiał debugować dezasemblację programu. Będzie to wymagało dobrej znajomości języka asemblera i jak działa alokacja pamięci w systemie Linux zrozumieć dane na stosie i w rejestrach.
Uruchamianie programu w GDB
Program w GDB można uruchomić na kilka sposobów. Albo wpisz gdb , a po załadowaniu wpisz uruchomić. Lub uruchom gdb, a następnie użyj plik polecenie, załaduj plik binarny do gdb, a następnie wykonaj go za pomocą uruchomić Komenda.
Jeśli Twój program do poprawnego działania wymaga argumentów wiersza poleceń, pamiętaj o dodaniu argumentów po nazwie programu. Oto składnia ładowania programu do GDB i wykonywania go z argumentami:
gdb
run
Lub:
gdb
file
run
Ustawianie punktów przerwania za pomocą GDB
Punkty przerwania w debugowaniu to ręcznie ustawiane twarde zatrzymania w kodzie, które zatrzymują wykonywanie, gdy program osiągnie punkt przerwania. Ustawianie punktów przerwania umożliwia przechodzenie przez kod i sprawdzanie, jak każdy etap wykonywania wpływa na dane i zmienne.
W GDB, gdy debugujesz program za pomocą symboli debugowania, możesz ustawić punkt przerwania według nazwy funkcji lub ustawić punkt przerwania na podstawie numeru linii. Oto składnia:
break main
break 47
Aby wyświetlić wszystkie punkty przerwania w bieżącej sesji debugowania, wpisz:
info breakpoints
Aby usunąć konkretny punkt przerwania lub wiele punktów przerwania, wpisz:
delete 2
delete 3-5
GDB umożliwia także ustawienie warunkowych punktów przerwania, co oznacza, że program zatrzyma się tylko wtedy, gdy podczas wykonywania zostanie spełniony określony warunek. Może to być zmiana wartości zmiennej, nieudane wywołanie funkcji lub cokolwiek innego. Oto składnia ustawiania warunkowych punktów przerwania:
break if n == 2
Jeśli chcesz kontynuować wykonywanie programu po uderzeniu w punkt przerwania, wpisz Kontynuować Komenda:
continue
Przechodzenie przez kod
Przechodzenie przez kod ma kluczowe znaczenie dla zrozumienia, w jaki sposób program obsługuje dane. Przechodząc przez różne funkcje programu i sprawdzając stan danych, możesz lepiej zrozumieć, w jaki sposób program implementuje logikę napisaną w kodzie.
Pomaga także wykryć przyczynę awarii i zbadać zachowanie programu z chirurgiczną precyzją, ponieważ możesz przejść przez każdą linię kodu według własnego uznania. W GDB możesz przeglądać kod na trzy podstawowe sposoby:
- krok: To polecenie mówi GDB, aby przeszedł do następnej linii pliku źródłowego. Pozwala to zasadniczo przemierzać długość kodu źródłowego linia po linii.
- Następny: To polecenie wykonuje następny wiersz kodu źródłowego wewnątrz bieżącej funkcji, a następnie zatrzymuje się. Następny traktuje funkcję jako pojedynczą linię, więc jeśli użyjesz next przed wywołaniem funkcji, potraktuje ją jako pojedynczą linię i przekroczy ją, w przeciwieństwie do krok Komenda.
- skończyć: Polecenie zakończenia wykonuje wszystkie pozostałe wiersze bieżącej funkcji, a następnie zatrzymuje się.
Badanie zmiennych
Przechodząc przez kod, warto sprawdzić wartości zmiennych, aby zobaczyć, jak zmienia je logika programu. Oto składnia przeglądania wartości zmiennych w GDB:
print
Jeżeli chcesz wydrukować zmiany wartości zmiennej przy każdej jej aktualizacji, powinieneś użyć polecenia display. Jest to szczególnie przydatne, gdy chcesz śledzić i drukować wartość zmiennej w pętli:
display
Ustawianie punktów obserwacyjnych
Punkty obserwacyjne i warunkowe punkty przerwania są ze sobą ściśle powiązane, ponieważ oba reagują na zmiany w programie. Punkty obserwacyjne służą do śledzenia zmian danych w kodzie. Na przykład możesz chcieć, aby program przerywał działanie przy każdej zmianie wartości zmiennej. Oto jak to zrobić za pomocą GDB:
watch
Debugowanie specyficzne dla wątku za pomocą GDB
GDB umożliwia debugowanie specyficzne dla wątku podczas pracy z programami wielowątkowymi. W celach demonstracyjnych będziemy pracować z prostym programem w języku C, który używa czterech wątków do drukowania komunikatów w każdym wątku.
Aby wyświetlić aktualnie utworzone wątki w programie, użyj opcji informacje Komenda:
info threads
Aby pracować z konkretnym wątkiem, możesz wybrać go z listy, korzystając z jego numeru indeksu. Na przykład:
thread 2
Po wybraniu wątku możesz przejść przez jego wykonanie za pomocą krok, Następny, I skończyć polecenia, jak pokazano powyżej.
Zdalne debugowanie za pomocą GDB
Można także zdalnie debugować programy znajdujące się w innym systemie. Aby to zrobić, musisz skonfigurować gdbserver na komputerze docelowym. Możesz go łatwo zainstalować za pomocą domyślnego menedżera pakietów swojej dystrybucji lub inne zainstalowane menedżery pakietów w Twoim systemie.
Na przykład, aby zainstalować gdbserver w systemach opartych na Ubuntu lub Debianie, użyj APT:
sudo apt install gdbserver
Po zainstalowaniu przejdź do folderu binarnego i uruchom to polecenie, aby uruchomić gdbserver:
gdbserver :
gdbserver powinien zwrócić informację, że działa i nasłuchuje na zdefiniowanym porcie. Teraz na komputerze klienckim uruchom GDB, a następnie połącz się ze zdalnym serwerem za pomocą cel Komenda:
target remote :
Pisanie skryptów GDB w celu automatyzacji debugowania
GDB umożliwia programistom pisanie skryptów GDB, które będą automatycznie wykonywać polecenia GDB. Jest to niezwykle pomocne, gdy próbujesz wielokrotnie debugować tę samą część kodu. Zamiast ustawiać punkt przerwania, przechodzić przez kod i drukować wartości zmiennych przy każdym ładowaniu pliku binarnego, możesz użyć skryptu GDB, aby zautomatyzować cały proces.
Oto przykład:
set logging enabled on
set logging file sample.out
break main
command 1
backtrace
print N
continue
end
quit
W powyższym skrypcie mówisz GDB, aby włączył rejestrowanie i zapisał dziennik w pliku o nazwie próbka.wyjście, a następnie ustaw punkt przerwania w główny funkcjonować.
Dla punktu przerwania numer 1, w tym przypadku punktu przerwania w funkcji main, uruchom następujące polecenia: ślad wsteczny, wydrukować, Kontynuować. Zasadniczo GDB najpierw uruchomi śledzenie wsteczne, następnie wydrukuje wartość zmiennej „N”, będzie kontynuować wykonywanie i na koniec zakończy działanie.
Aby wykonać ten skrypt, użyj:
gdb -x