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.

instagram viewer

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:

  1. 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.
  2. 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.
  3. 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