Îmbunătățiți calitatea codului și preveniți rezultatele neașteptate, învățând cum să utilizați GNU Debugger pentru a dezvălui erori nedorite din codul dvs.

Depanarea este o abilitate indispensabilă pentru programatori și cercetătorii de securitate. Având o înțelegere puternică a depanării, vă permite să înțelegeți un executabil la un nivel inferior și să detectați orice erori ascunse.

Depanatorul GNU sau, GDB, este un instrument de depanare atemporal pe care programatori se bazează de ani de zile. Iată cum să utilizați GDB pe Linux.

Pregătirea exemplelor de programe

Pentru a explora caracteristicile GDB, veți avea nevoie de un executabil cu care să experimentați. Pentru demonstrație, veți rula GDB într-un program de verificare a cheilor o dată cu codul sursă și simbolurile de depanare disponibile, o dată fără cod sursă și pe un program simplu cu mai multe fire care imprimă mesaje pe ecran, atât scrise în C, cât și compilate cu GCC (GNU C Compilator).

Puteți utilizați orice alt compilator C dar asigurați-vă că nu îndepărtați binarul.

instagram viewer

Cel mai probabil veți rula GDB pe propriile programe. Așa că asigurați-vă că le compilați cu -g marcați cu gcc pentru a activa simbolurile de depanare.

Fără simbolurile de depanare prezente și cu un binar puternic decapat, va trebui să depanați dezasamblarea programului. Acest lucru va necesita să aveți o înțelegere puternică a limbajului de asamblare și cum funcționează alocarea memoriei pe Linux pentru a înțelege datele din stivă și registre.

Rularea unui program în GDB

Rulați un program în GDB în câteva moduri. Ori introduceți gdb , iar odată ce se încarcă, tastați alerga. Sau porniți gdb și apoi folosiți fişier comanda, încărcați binarul în gdb și apoi executați-l cu alerga comanda.

Dacă programul dumneavoastră necesită argumente de linie de comandă pentru a funcționa corect, asigurați-vă că adăugați argumentele după numele programului. Iată sintaxa pentru încărcarea programului pe GDB și executarea lui cu argumente:

gdb 
run

Sau:

gdb
file
run

Setarea punctelor de întrerupere cu GDB

Punctele de întrerupere în depanare sunt setate manual opriri dure în cod care opresc fluxul de execuție atunci când programul atinge un punct de întrerupere. Setarea punctelor de întrerupere vă permite să parcurgeți codul și să inspectați modul în care fiecare etapă de execuție afectează datele și variabilele.

În GDB, atunci când depanați un program cu simboluri de depanare, puteți fie să setați un punct de întrerupere după numele funcției, fie să setați un punct de întrerupere pe baza numărului de linie. Iată sintaxa:

break main
break 47

Pentru a vedea toate punctele de întrerupere din sesiunea curentă de depanare, tastați:

info breakpoints

Pentru a șterge un anumit punct de întrerupere sau mai multe puncte de întrerupere, tastați:

delete 2
delete 3-5

GDB vă permite, de asemenea, să setați puncte de întrerupere condiționate, ceea ce înseamnă că programul se va opri numai dacă o anumită condiție este îndeplinită în timpul execuției. Ar putea fi modificarea valorii unei variabile sau a unui apel de funcție nereușit sau orice doriți. Iată sintaxa pentru a seta punctele de întrerupere condiționate:

break  if n == 2

Dacă doriți să continuați execuția programului după ce atingeți un punct de întrerupere, introduceți continua comanda:

continue

Trecerea prin cod

Trecerea prin cod este crucială pentru a înțelege modul în care programul gestionează datele. Parcurgând diverse funcții din program și examinând starea datelor, puteți obține o mai bună înțelegere a modului în care programul implementează logica pe care ați scris-o în cod.

De asemenea, vă ajută să detectați rădăcina erorilor și să studiați comportamentul programului cu precizie chirurgicală, deoarece puteți parcurge fiecare linie de cod după cum doriți. Puteți parcurge codul în trei moduri principale în GDB:

  1. Etapa: Această comandă îi spune GDB să pășească în următoarea linie a fișierului sursă. Acest lucru vă permite în esență să traversați lungimea codului sursă linie cu linie.
  2. Următorul: Această comandă execută următoarea linie de cod sursă în interiorul funcției curente și apoi se oprește. Următorul tratează o funcție ca pe o singură linie, așa că dacă utilizați următoarea înainte de un apel de funcție, o va trata ca pe o singură linie și va trece peste ea, spre deosebire de Etapa comanda.
  3. finalizarea: Comanda finish execută toate liniile rămase în interiorul funcției curente și apoi se oprește.

Examinarea variabilelor

Pe măsură ce parcurgeți codul, ați dori să examinați valoarea variabilelor pentru a vedea cum le schimbă logica programului. Iată sintaxa pentru a vedea valoarea variabilelor din GDB:

print 

În cazul în care doriți să imprimați modificările valorii unei variabile de fiecare dată când aceasta este actualizată, ar trebui să utilizați comanda display. Acest lucru este util în special atunci când doriți să urmăriți și să imprimați valoarea unei variabile într-o buclă:

display 

Setarea punctelor de supraveghere

Punctele de urmărire și punctele de întrerupere condiționate sunt strâns legate, deoarece ambele răspund la modificările unui program. Punctele de urmărire sunt folosite pentru a urmări modificările datelor din cod. De exemplu, ați putea dori ca programul să se întrerupă ori de câte ori valoarea unei variabile se schimbă. Iată cum se face acest lucru cu GDB:

watch 

Depanare specifică firelor cu GDB

GDB vă permite să efectuați o depanare specifică firelor atunci când lucrați cu programe cu mai multe fire. Pentru demonstrație, vom lucra cu un program C simplu care folosește patru fire pentru a imprima mesaje cu fiecare fir.

Pentru a vedea firele generate în prezent în programul dvs., utilizați info comanda:

info threads

Pentru a lucra cu un anumit fir, îl puteți selecta din listă folosind numărul său de index. De exemplu:

thread 2

După selectarea firului de execuție, puteți parcurge fluxul de execuție folosind Etapa, Următorul, și finalizarea comenzi așa cum a fost demonstrat mai sus.

Depanare de la distanță cu GDB

De asemenea, puteți depana de la distanță programele situate pe un alt sistem. Pentru a face acest lucru, trebuie să configurați gdbserver pe mașina țintă. Îl puteți instala cu ușurință folosind managerul de pachete implicit al distribuției dvs. sau alți manageri de pachete pe care i-ați instalat pe sistemul dvs.

De exemplu, pentru a instala gdbserver pe sistemele dumneavoastră Ubuntu sau Debian, utilizați APT:

sudo apt install gdbserver

Odată instalat, treceți în folderul binarului și rulați această comandă pentru a porni gdbserver:

gdbserver :

gdbserver ar trebui să returneze ieșirea care este activată și ascultă pe portul pe care l-ați definit. Acum, pe computerul client, porniți GDB și apoi conectați-vă la serverul de la distanță folosind ţintă comanda:

target remote :

Scrierea de scripturi GDB pentru a automatiza depanarea

GDB permite programatorilor să scrie scripturi GDB care vor executa automat comenzile GDB. Acest lucru vă ajută enorm atunci când încercați să depanați de mai multe ori aceeași parte a unui cod. În loc să fie nevoie să setați punctul de întrerupere, să parcurgeți codul și să imprimați valorile variabilelor de fiecare dată când încărcați binarul, puteți utiliza un script GDB pentru a automatiza întregul proces.

Iată un exemplu:

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

În scriptul de mai sus, îi spuneți GDB să activeze înregistrarea și să salveze jurnalul într-un fișier numit eşantion.out, apoi setați un punct de întrerupere la principal funcţie.

Pentru punctul de întrerupere numărul 1, în acest caz, punctul de întrerupere la funcția principal, rulați următoarele comenzi: trage înapoi, imprimare, continua. Practic, GDB va rula mai întâi un backtrace, apoi va tipări valoarea variabilei „N”, va continua execuția și, în final, va renunța.

Pentru a executa acest script, utilizați:

gdb -x