Förbättra kodkvaliteten och förhindra oväntade resultat genom att lära dig hur du använder GNU Debugger för att avslöja oönskade buggar i din kod.

Felsökning är en oumbärlig färdighet för programmerare och säkerhetsforskare. Genom att ha ett starkt grepp om felsökning kan du förstå en körbar fil på en lägre nivå och fånga eventuella lurande fel.

GNU debugger eller GDB, är ett tidlöst felsökningsverktyg som har förlitats på av programmerare i flera år nu. Så här använder du GDB på Linux.

Förbereder exempelprogram

För att utforska funktionerna i GDB behöver du en körbar fil att experimentera med. För demonstration kommer du att köra GDB på ett nyckelkontrollprogram en gång med källkod och felsökningssymboler tillgängliga, en gång utan källkod, och på ett enkelt flertrådigt program som skriver ut meddelanden till skärmen, både skrivna i C och kompilerade med GCC (GNU C Kompilator).

Du kan använd vilken annan C-kompilator som helst men se till att inte ta bort binären.

Du kommer med största sannolikhet att köra GDB på dina egna program. Så se till att kompilera dem med

instagram viewer
-g flagga med gcc för att aktivera felsökningssymboler.

Utan debug-symbolerna närvarande och med en kraftigt avskalad binär, måste du felsöka demonteringen av programmet. Detta kräver att du har ett starkt grepp om assemblerspråk och hur minnesallokering fungerar på Linux att förstå data i stacken och registren.

Köra ett program i GDB

Du kör ett program i GDB på ett par sätt. Skriv antingen in gdb , och när den har laddats, skriv springa. Eller starta gdb och använd sedan fil kommandot, ladda binären till gdb och kör den sedan med springa kommando.

Om ditt program kräver kommandoradsargument för att fungera korrekt, se till att lägga till argumenten efter programnamnet. Här är syntaxen för att ladda programmet till GDB och köra det med argument:

gdb 
run

Eller:

gdb
file
run

Ställa in brytpunkter med GDB

Brytpunkter vid felsökning är manuellt inställda hårda stopp i kod som stoppar flödet av exekvering när programmet når en brytpunkt. Genom att ställa in brytpunkter kan du stega igenom koden och inspektera hur varje steg i exekveringen påverkar data och variabler.

I GDB, när du felsöker ett program med felsökningssymboler, kan du antingen ställa in en brytpunkt med namnet på funktionen eller ställa in en brytpunkt baserat på radnumret. Här är syntaxen:

break main
break 47

För att se alla brytpunkter i den aktuella felsökningssessionen, skriv:

info breakpoints

För att ta bort en viss brytpunkt eller flera brytpunkter, skriv:

delete 2
delete 3-5

GDB låter dig också ställa in villkorliga brytpunkter, vilket innebär att programmet bara kommer att stanna om ett visst villkor är uppfyllt under körningen. Det kan vara förändringen i värdet på en variabel eller ett misslyckat funktionsanrop eller vad du vill. Här är syntaxen för att ställa in villkorliga brytpunkter:

break  if n == 2

Om du vill fortsätta köra programmet efter att ha träffat en brytpunkt, skriv in Fortsätta kommando:

continue

Gå igenom koden

Att gå igenom koden är avgörande för att förstå hur programmet hanterar data. Genom att gå igenom olika funktioner i ditt program och undersöka datatillståndet kan du få en bättre förståelse för hur programmet implementerar logiken du har skrivit i kod.

Det hjälper dig också att upptäcka roten till krascher och studera programbeteende med kirurgisk precision eftersom du kan gå igenom varje kodrad som du vill. Du kan stega igenom koden på tre primära sätt i GDB:

  1. steg: Detta kommando säger till GDB att gå in på nästa rad i källfilen. Detta gör att du i huvudsak kan korsa längden på källkoden rad för rad.
  2. Nästa: Detta kommando kör nästa rad med källkod i den aktuella funktionen och stoppar sedan. Nästa behandlar en funktion som en enda rad så om du använder nästa före ett funktionsanrop kommer den att behandla den som en enda rad och gå över den, till skillnad från steg kommando.
  3. Avsluta: Kommandot finish utför alla återstående rader i den aktuella funktionen och stoppar sedan.

Undersöka variabler

När du går igenom koden vill du undersöka värdet på variabler för att se hur programlogiken ändrar dem. Här är syntaxen för att se värdet på variabler i GDB:

print 

Om du vill skriva ut ändringarna i värdet på en variabel varje gång den uppdateras, bör du använda kommandot display. Detta är särskilt användbart när du vill spåra och skriva ut värdet på en variabel i en loop:

display 

Ställa in vaktpunkter

Watchpoints och villkorliga brytpunkter är nära relaterade eftersom de båda reagerar på ändringar i ett program. Watchpoints används för att spåra förändringar i data i koden. Till exempel kanske du vill att programmet ska gå sönder när värdet på en variabel ändras. Så här gör du det med GDB:

watch 

Trådspecifik felsökning med GDB

GDB låter dig utföra trådspecifik felsökning när du arbetar med flertrådade program. För demonstration kommer vi att arbeta med ett enkelt C-program som använder fyra trådar för att skriva ut meddelanden med varje tråd.

För att se de för närvarande skapade trådarna i ditt program, använd info kommando:

info threads

För att arbeta med en specifik tråd kan du välja den från listan med hjälp av dess indexnummer. Till exempel:

thread 2

När du har valt tråden kan du gå igenom dess exekveringsflöde med hjälp av steg, Nästa, och Avsluta kommandon som visas ovan.

Fjärrfelsökning med GDB

Du kan också fjärrfelsöka program som finns på ett annat system. För att göra det måste du ställa in gdbserver på måldatorn. Du kan enkelt installera det med hjälp av standardpakethanteraren för din distribution eller andra pakethanterare som du har installerat på ditt system.

Till exempel, för att installera gdbserver på ditt Ubuntu- eller Debian-baserade system, använd APT:

sudo apt install gdbserver

När det är installerat, flytta in i mappen för binären och kör det här kommandot för att starta gdbserver:

gdbserver :

gdbserver bör returnera utdata som den är uppe och lyssnar på på den port du definierat. Starta nu GDB på klientdatorn och anslut sedan till fjärrservern med hjälp av mål kommando:

target remote :

Skriva GDB-skript för att automatisera felsökning

GDB tillåter programmerare att skriva GDB-skript som kör GDB-kommandon automatiskt. Detta hjälper oerhört när du försöker felsöka samma del av en kod flera gånger. Istället för att behöva ställa in brytpunkten, stega igenom koden och skriva ut variabelvärden varje gång du laddar binären, kan du använda ett GDB-skript för att automatisera hela processen.

Här är ett exempel:

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

I skriptet ovan säger du till GDB att aktivera loggning och spara loggen till en fil som heter prov.ut, ställ sedan in en brytpunkt vid huvud fungera.

För brytpunkt nummer 1, i det här fallet, brytpunkten vid funktion huvud, kör följande kommandon: bakåtspårning, skriva ut, Fortsätta. I grund och botten kommer GDB först att köra en bakåtspårning, sedan skriva ut värdet på variabeln "N", fortsätta körningen och slutligen avsluta.

För att köra detta skript, använd:

gdb -x