Verbeter de kwaliteit van de code en voorkom onverwachte resultaten door te leren hoe u GNU Debugger kunt gebruiken om ongewenste bugs in uw code aan het licht te brengen.

Debuggen is een onmisbare vaardigheid voor programmeurs en beveiligingsonderzoekers. Als u goed inzicht heeft in debuggen, kunt u een uitvoerbaar bestand op een lager niveau begrijpen en eventuele fouten opsporen.

De GNU-debugger, of GDB, is een tijdloze debugging-tool waar programmeurs al jaren op vertrouwen. Hier leest u hoe u GDB op Linux gebruikt.

Voorbeeldprogramma's voorbereiden

Om de functies van GDB te verkennen, heb je een uitvoerbaar bestand nodig om mee te experimenteren. Ter demonstratie draait u GDB één keer in een sleutelcontroleprogramma met beschikbare broncode en debug-symbolen, één keer zonder broncode, en op een eenvoudig multithreaded programma dat berichten op het scherm afdrukt, zowel geschreven in C als gecompileerd met GCC (GNU C Compiler).

Jij kan gebruik een andere C-compiler maar zorg ervoor dat u het binaire bestand niet verwijdert.

instagram viewer

Waarschijnlijk draait u GDB op uw eigen programma's. Zorg er dus voor dat u ze compileert met de -G markeer met gcc om foutopsporingssymbolen in te schakelen.

Zonder de aanwezige debug-symbolen en met een zwaar gestript binair bestand, zul je de demontage van het programma moeten debuggen. Hiervoor is een goede kennis van de assembleertaal vereist hoe geheugentoewijzing werkt op Linux om de gegevens in de stapel en registers te begrijpen.

Een programma uitvoeren in GDB

Je voert een programma in GDB op een aantal manieren uit. Typ het in gdb , en zodra het is geladen, typt u loop. Of start gdb en gebruik vervolgens de bestand commando, laad het binaire bestand in gdb en voer het vervolgens uit met de loop commando.

Als uw programma opdrachtregelargumenten nodig heeft om goed te kunnen functioneren, zorg er dan voor dat u de argumenten achter de programmanaam toevoegt. Hier is de syntaxis voor het laden van het programma in GDB en het uitvoeren ervan met argumenten:

gdb 
run

Of:

gdb
file
run

Breekpunten instellen met GDB

Breekpunten bij het debuggen zijn handmatig ingestelde harde stops in code die de uitvoeringsstroom stoppen wanneer het programma een breekpunt bereikt. Door breekpunten in te stellen, kunt u stapsgewijs door de code lopen en inspecteren hoe elke uitvoeringsfase gegevens en variabelen beïnvloedt.

Wanneer u in GDB een programma debugt met debug-symbolen, kunt u een breekpunt instellen op basis van de naam van de functie of een breekpunt instellen op basis van het regelnummer. Hier is de syntaxis:

break main
break 47

Om alle breekpunten in de huidige foutopsporingssessie te bekijken, typt u:

info breakpoints

Om een ​​bepaald breekpunt of meerdere breekpunten te verwijderen, typt u:

delete 2
delete 3-5

Met GDB kunt u ook voorwaardelijke breekpunten instellen, wat betekent dat het programma alleen stopt als tijdens de uitvoering aan een bepaalde voorwaarde wordt voldaan. Het kan de verandering in de waarde van een variabele zijn, of een mislukte functieaanroep, of wat u maar wilt. Hier is de syntaxis om voorwaardelijke breekpunten in te stellen:

break  if n == 2

Als u de uitvoering van het programma wilt voortzetten nadat u een onderbrekingspunt heeft bereikt, typt u het doorgaan commando:

continue

Door de code stappen

Het doorlopen van de code is van cruciaal belang om te begrijpen hoe het programma met de gegevens omgaat. Door verschillende functies in uw programma te doorlopen en de status van de gegevens te onderzoeken, kunt u een beter inzicht krijgen in hoe het programma de logica implementeert die u in code hebt geschreven.

Het helpt je ook om de oorzaak van crashes en het gedrag van het studieprogramma met chirurgische precisie op te sporen, omdat je elke coderegel naar wens kunt doorlopen. U kunt in GDB op drie manieren door de code stappen:

  1. stap: Dit commando vertelt GDB om naar de volgende regel van het bronbestand te gaan. Hierdoor kunt u in essentie de lengte van de broncode regel voor regel doorlopen.
  2. volgende: Deze opdracht voert de volgende regel broncode uit binnen de huidige functie en stopt vervolgens. volgende behandelt een functie als een enkele regel, dus als u next gebruikt vóór een functieaanroep, zal deze deze als een enkele regel behandelen en eroverheen stappen, in tegenstelling tot de functie stap commando.
  3. finish: Het finishcommando voert alle resterende regels binnen de huidige functie uit en stopt vervolgens.

Variabelen onderzoeken

Terwijl u door de code loopt, wilt u de waarde van variabelen onderzoeken om te zien hoe de programmalogica deze verandert. Hier is de syntaxis om de waarde van variabelen in GDB te bekijken:

print 

Als u de veranderingen in de waarde van een variabele wilt afdrukken telkens wanneer deze wordt bijgewerkt, moet u het display-commando gebruiken. Dit is vooral handig als u de waarde van een variabele in een lus wilt volgen en afdrukken:

display 

Controlepunten instellen

Controlepunten en voorwaardelijke breekpunten zijn nauw met elkaar verbonden, omdat ze beide reageren op veranderingen in een programma. Watchpoints worden gebruikt om wijzigingen in gegevens in de code bij te houden. U wilt bijvoorbeeld dat het programma stopt wanneer de waarde van een variabele verandert. Zo doet u dit met GDB:

watch 

Thread-specifieke foutopsporing met GDB

Met GDB kunt u threadspecifieke foutopsporing uitvoeren wanneer u met multithreaded programma's werkt. Ter demonstratie gaan we werken met een eenvoudig C-programma dat vier threads gebruikt om bij elke thread berichten af ​​te drukken.

Om de momenteel gegenereerde threads in uw programma te bekijken, gebruikt u de informatie commando:

info threads

Om met een specifieke thread te werken, kunt u deze uit de lijst selecteren met behulp van het indexnummer. Bijvoorbeeld:

thread 2

Nadat u de thread heeft geselecteerd, kunt u door de uitvoeringsstroom stappen met behulp van de stap, volgende, En finish commando's zoals hierboven gedemonstreerd.

Foutopsporing op afstand met GDB

U kunt ook op afstand fouten opsporen in programma's die zich op een ander systeem bevinden. Om dit te doen, moet u gdbserver op de doelmachine instellen. U kunt het eenvoudig installeren met behulp van de standaard pakketbeheerder van uw distributie of andere pakketbeheerders die u hebt geïnstalleerd op uw systeem.

Om bijvoorbeeld gdbserver op uw Ubuntu- of Debian-gebaseerde systemen te installeren, gebruikt u APT:

sudo apt install gdbserver

Eenmaal geïnstalleerd, ga naar de map van het binaire bestand en voer deze opdracht uit om gdbserver te starten:

gdbserver :

gdbserver zou de uitvoer moeten retourneren dat deze actief is en luistert op de poort die u hebt gedefinieerd. Start nu op de clientcomputer GDB en maak vervolgens verbinding met de externe server met behulp van de doel commando:

target remote :

GDB-scripts schrijven om foutopsporing te automatiseren

Met GDB kunnen programmeurs GDB-scripts schrijven die GDB-opdrachten automatisch uitvoeren. Dit helpt enorm wanneer u hetzelfde deel van een code meerdere keren probeert te debuggen. In plaats van dat u elke keer dat u het binaire bestand laadt het breekpunt moet instellen, de code moet doorlopen en variabelewaarden moet afdrukken, kunt u een GDB-script gebruiken om het hele proces te automatiseren.

Hier is een voorbeeld:

set logging enabled on
set logging file sample.out
break main
command 1
backtrace
print N
continue
end
quit

In het bovenstaande script vertel je GDB om logboekregistratie in te schakelen en het logboek op te slaan in een bestand met de naam monster.uiten stel vervolgens een breekpunt in op de voornaamst functie.

Voor breekpunt nummer 1, in dit geval het breekpunt bij de functie main, voert u de volgende opdrachten uit: terugspoor, afdrukken, doorgaan. In principe zal GDB eerst een backtrace uitvoeren, vervolgens de waarde van de variabele "N" afdrukken, de uitvoering voortzetten en uiteindelijk stoppen.

Om dit script uit te voeren, gebruikt u:

gdb -x