Forbedre kodekvaliteten og forhindre uventede resultater ved å lære hvordan du bruker GNU Debugger for å avsløre uønskede feil i koden din.

Feilsøking er en uunnværlig ferdighet for programmerere og sikkerhetsforskere. Å ha et godt grep om feilsøking lar deg forstå en kjørbar på et lavere nivå og fange opp eventuelle lurende feil.

GNU debugger eller, GDB, er et tidløst feilsøkingsverktøy som har vært stolt på av programmerere i mange år nå. Slik bruker du GDB på Linux.

Forberede prøveprogrammer

For å utforske funksjonene til GDB trenger du en kjørbar fil å eksperimentere med. For demonstrasjon vil du kjøre GDB på et nøkkelkontrollprogram én gang med kildekode og feilsøkingssymboler tilgjengelig, én gang uten kildekode, og på et enkelt flertråds program som skriver ut meldinger til skjermen, både skrevet i C og kompilert med GCC (GNU C kompilator).

Du kan bruk en hvilken som helst annen C-kompilator men pass på at du ikke stripper binæren.

Du vil mest sannsynlig kjøre GDB på dine egne programmer. Så sørg for å kompilere dem med -g flagg med gcc for å aktivere feilsøkingssymboler.

Uten feilsøkingssymbolene til stede og med en kraftig strippet binærfil, må du feilsøke demonteringen av programmet. Dette vil kreve at du har et godt grep om assemblerspråk og hvordan minnetildeling fungerer på Linux for å forstå dataene i stabelen og registrene.

Kjøre et program i GDB

Du kjører et program i GDB på et par måter. Skriv inn enten gdb , og når den har lastet opp, skriv løpe. Eller start gdb og bruk deretter fil kommandoen, last inn binærfilen i gdb, og utfør den deretter med løpe kommando.

Hvis programmet krever kommandolinjeargumenter for å fungere ordentlig, sørg for å legge til argumentene etter programnavnet. Her er syntaksen for å laste programmet til GDB og kjøre det med argumenter:

gdb 
run

Eller:

gdb
file
run

Sette bruddpunkter med GDB

Knekkpunkter i feilsøking er manuelt innstilte harde stopp i kode som stopper kjøringen når programmet når et bruddpunkt. Ved å angi bruddpunkter kan du gå gjennom koden og inspisere hvordan hvert trinn i utførelse påvirker data og variabler.

I GDB, når du feilsøker et program med feilsøkingssymboler, kan du enten angi et bruddpunkt med navnet på funksjonen eller sette et bruddpunkt basert på linjenummeret. Her er syntaksen:

break main
break 47

For å se alle bruddpunkter i gjeldende feilsøkingsøkt, skriv inn:

info breakpoints

For å slette et bestemt bruddpunkt eller flere bruddpunkter, skriv inn:

delete 2
delete 3-5

GDB lar deg også sette betingede bruddpunkter, noe som betyr at programmet bare stopper hvis en bestemt betingelse er oppfylt under utførelse. Det kan være endringen i verdien av en variabel eller mislykket funksjonskall eller hva du vil. Her er syntaksen for å angi betingede bruddpunkter:

break  if n == 2

Hvis du ønsker å fortsette kjøringen av programmet etter å ha truffet et bruddpunkt, skriv inn Fortsette kommando:

continue

Gå gjennom kode

Å gå gjennom koden er avgjørende for å forstå hvordan programmet håndterer dataene. Ved å gå gjennom ulike funksjoner i programmet og undersøke datatilstanden, kan du få en bedre forståelse av hvordan programmet implementerer logikken du har skrevet i kode.

Den hjelper deg også med å oppdage roten til krasj og studere programoppførsel med kirurgisk presisjon, ettersom du kan gå gjennom hver linje med kode som du ønsker. Du kan gå gjennom koden på tre primære måter i GDB:

  1. steg: Denne kommandoen forteller GDB å gå inn i neste linje i kildefilen. Dette lar deg i det vesentlige krysse lengden på kildekoden linje for linje.
  2. neste: Denne kommandoen utfører neste linje med kildekode i gjeldende funksjon og stopper deretter. neste behandler en funksjon som en enkelt linje, så hvis du bruker neste før et funksjonskall, vil den behandle den som en enkelt linje og gå over den, i motsetning til steg kommando.
  3. bli ferdig: Finish-kommandoen utfører alle de gjenværende linjene inne i gjeldende funksjon og stopper deretter.

Undersøke variabler

Når du går gjennom koden, ønsker du å undersøke verdien av variabler for å se hvordan programlogikken endrer dem. Her er syntaksen for å se verdien av variabler i GDB:

print 

Hvis du ønsker å skrive ut endringene i verdien til en variabel hver gang den oppdateres, bør du bruke display-kommandoen. Dette er spesielt nyttig når du vil spore og skrive ut verdien til en variabel i en løkke:

display 

Sette vaktpunkter

Vaktpunkter og betingede bruddpunkter er nært beslektet ettersom de begge reagerer på endringer i et program. Watchpoints brukes til å spore endringer i data i koden. For eksempel vil du kanskje at programmet skal brytes når verdien til en variabel endres. Slik gjør du det med GDB:

watch 

Trådspesifikk feilsøking med GDB

GDB lar deg utføre trådspesifikk feilsøking når du arbeider med flertrådede programmer. For demonstrasjon vil vi jobbe med et enkelt C-program som bruker fire tråder til å skrive ut meldinger med hver tråd.

For å se de nåværende trådene i programmet ditt, bruk info kommando:

info threads

For å jobbe med en spesifikk tråd kan du velge den fra listen ved å bruke indeksnummeret. For eksempel:

thread 2

Etter å ha valgt tråden kan du gå gjennom utførelsesflyten ved å bruke steg, neste, og bli ferdig kommandoer som vist ovenfor.

Ekstern feilsøking med GDB

Du kan også eksternt feilsøke programmer som ligger på et annet system. For å gjøre det, må du sette opp gdbserver på målmaskinen. Du kan enkelt installere den ved å bruke standard pakkebehandling for distribusjonen eller andre pakkebehandlere du har installert på systemet ditt.

For å installere gdbserver på Ubuntu eller Debian-baserte systemer, bruk APT:

sudo apt install gdbserver

Når den er installert, flytt inn i mappen til binæren og kjør denne kommandoen for å starte gdbserver:

gdbserver :

gdbserver skal returnere utgangen som den er oppe og lytter til på porten du definerte. Nå på klientmaskinen, start GDB og koble til den eksterne serveren ved hjelp av mål kommando:

target remote :

Skrive GDB-skript for å automatisere feilsøking

GDB lar programmerere skrive GDB-skript som vil utføre GDB-kommandoer automatisk. Dette hjelper enormt når du prøver å feilsøke den samme delen av en kode flere ganger. I stedet for å måtte angi bruddpunktet, gå gjennom kode og skrive ut variabelverdier hver gang du laster inn binæren, kan du bruke et GDB-skript for å automatisere hele prosessen.

Her er et eksempel:

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

I skriptet ovenfor ber du GDB aktivere logging og lagre loggen til en fil som heter sample.out, sett deretter et bruddpunkt ved hoved- funksjon.

For bruddpunkt nummer 1, i dette tilfellet, bruddpunktet ved funksjon hoved, kjør følgende kommandoer: tilbakesporing, skrive ut, Fortsette. I utgangspunktet vil GDB først kjøre en tilbakesporing, deretter skrive ut verdien av variabelen "N", fortsette kjøringen og til slutt avslutte.

For å utføre dette skriptet, bruk:

gdb -x