Kako koristiti gdbserver za udaljeno otklanjanje grešaka na Linuxu

Posljednje ažuriranje: 14/01/2026
Autor: Isaac
  • gdbserver djeluje kao udaljeni agent GDB-a za kontrolu procesa na drugoj mašini putem TCP-a ili serijskog porta.
  • Za udaljeno otklanjanje grešaka, ključno je kompajlirati sa simboliKoristite odgovarajuću gdb bazu podataka i pravilno konfigurirajte putanje simbola i fontova.
  • gdbserver nudi jednoprocesni i višeprocesni način rada, a također se integrira s WinDbg-om i QEMU-om za otklanjanje grešaka u kernelu.
  • Opcije kao što su --debug, sysroot i ograničenja veličine vrijednosti pomažu u dijagnosticiranju problema i stabilizaciji sesija.

Udaljeno otklanjanje grešaka pomoću gdbservera

Ako programirate u C ili C++ jeziku Linux i nikad nisi dirao gdbserverPropuštate jedan od najkorisnijih alata za udaljeno otklanjanje grešaka u procesima, bilo na serveru, ugrađenom sistemu ili čak unutar virtuelne mašine ili WSL-a. Daleko od toga da je nešto "magično" ili rezervisano za stručnjake, gdbserver je jednostavno mali program koji komunicira sa gdb-om i kontroliše izvršavanje ciljnog procesa.

Ključna ideja je vrlo jednostavna.: na mašini na kojoj se izvršava binarna datoteka koju želite debugirati (the cilj) pokrećete gdbserver; na vašem radnom računaru ( domaćinPokrećete gdb ili čak WinDbg sa podrškom za gdb protokol. Oba se povezuju putem TCP-a ili serijskog porta, i odatle možete postavljati tačke prekida, pregledavati varijable, pregledavati stek ili pratiti izvršavanje korak po korak kao da se program izvršava na vašem računaru.

Šta je gdbserver i kada ga je korisno koristiti?

Šta je gdbserver

gdbserver je udaljeni "agent" za otklanjanje grešaka za GNU gdb.Njegova funkcija je vrlo specifična: izvršava se na mašini na kojoj se izvršava program koji se analizira, kontroliše taj proces (ili procese) i komunicira sa gdb klijentom koji se nalazi na drugoj mašini (ili na istoj) putem udaljene veze.

U svakodnevnoj upotrebi, gdbserver se koristi u dva tipična scenarijaSoftver za otklanjanje grešaka koji radi u ugrađenim okruženjima (ruteri, ploče sa pojednostavljenim Linuxom, uređaji) IoTitd.) i procese debugiranja na udaljenim Linux mašinama, gdje nije zgodno ili jednostavno nije moguće imati "debelu" gdb bazu sa svim bibliotekama i simbolima.

Na praktičnom nivou, gdbserver obavlja zadatke kao što su Čitanje i pisanje registra procesa i memorije, kontrola izvršavanja (nastavak, pauza, prolazak kroz korake), upravljanje tačkama prekida i slanje svih ovih podataka gdb-u koristeći GDB udaljeni protokol. Ova filozofija je vrlo slična onoj kod alata poput OpenOCD-a, koji djeluju kao most između gdb-a i hardver eksterni, s tom razlikom što gdbserver radi na istom sistemu na kojem se pokreće i binarna datoteka.

Ako dolazite iz okruženja Windows Također je zanimljivo znati Debuggeri poput WinDbg-a mogu komunicirati s gdbserverom na Linuxu, tako da možete debugirati korisničke procese na Linuxu iz WinDbg-a koristeći podršku za udaljeno debugiranje putem gdb protokola koji je Microsoft uključio u novije verzije.

Osnovni zahtjevi za debagovanje sa gdb i gdbserver

Zahtjevi za korištenje gdbservera

Prije nego što započnete udaljeno otklanjanje grešaka, morate razumjeti odnos host/cilj.. u cilj To je mašina na kojoj se izvršava program koji treba debagovati i na kojoj će se izvršavati gdbserver; domaćin Ovo je mašina s koje ćete pokretati gdb (ili WinDbg) i gdje ćete imati izvorni kod i, po mogućnosti, simbole za otklanjanje grešaka.

Osnovna početna tačka je kompajliranje binarnog fajla sa simbolimaU GCC-u ili g++-u ovo se postiže pomoću zastavice -gi obično je preporučljivo onemogućiti optimizacije (na primjer sa -O0Ovo omogućava debuggeru da preciznije prikaže varijable, makroe i strukturu koda. Za određene makroe možete koristiti više nivoe debugiranja, kao što su -g3.

Na strani hosta će vam trebati kompatibilna verzija gdb-a. sa ciljnom arhitekturom. Za debugiranje MIPS, ARM ili ugrađenog sistema druge arhitekture, morate koristiti gdb odgovarajućeg cross-toolchain-a (na primjer) arm-none-eabi-gdb o gdb-multiarch) i, ako je potrebno, konfigurirati arhitekturu i endianness sa naredbe como set arch y set endian.

Što se tiče veze, gdbserver podržava dva glavna tipaSerijska veza (vrlo česta u ugrađenom hardveru, putem UART-a) i TCP/IP, što je najpogodnije kada je cilj na istoj mreži ili je Linux mašina dostupna preko mreže. U oba slučaja, komanda se koristi iz gdb-a. target remote za povezivanje s krajnjom tačkom koju je otkrio gdbserver.

Načini pokretanja gdbservera: jednoprocesni i višeprocesni način rada

načini izvršavanja gdbservera

gdbserver može raditi na dva glavna načina Kada govorimo o debuggiranju u korisničkom režimu: direktno povezano s jednim procesom ili kao "server procesa" koji omogućava listanje i povezivanje s različitim sistemskim procesima.

U režimu jednog procesa Pokrećete gdbserver, navodeći host:port i program koji treba pokrenuti. U jednostavnom primjeru na Linux desktop računaru, mogli biste uraditi nešto poput ovoga:

Naredba: gdbserver localhost:3333 foo

Sa tom komandom, gdbserver pokreće binarni fajl. foo i on ostaje slušati na portu 3333Sve dok se udaljeni gdb ne poveže, program ostaje zaustavljen; kada se gdb poveže sa target remote localhost:3333, proces počinje kontrolirati descrusher.

U višeprocesnom režimu (procesni server) ova opcija se koristi --multiU ovom slučaju, gdbserver ne pokreće direktno nijedan program, već jednostavno osluškuje dolazne veze i omogućava klijentu (gdb ili WinDbg) da upravlja kojim procesima će se kreirati ili pripojiti:

  Google lansira Gemini Code Assist: besplatni pomoćnik za programiranje koji pokreće AI

Naredba: gdbserver --multi localhost:1234

Prilikom rada sa WinDbg-om na Linuxu, ovaj višenamjenski način rada je posebno zanimljiv.Zato što iz samog WinDbg-a možete izlistati procese na udaljenom sistemu, vidjeti PID, korisnika i komandnu liniju, te se pridružiti onome koji vas zanima, slično kao što se to radi sa procesnim serverom. dbgsrv.exe na Windows-u.

Udaljeno otklanjanje grešaka pomoću gdbserver-a i gdb-a korak po korak

Hajde da ovo objasnimo jednim vrlo tipičnim primjerom.Debagirajte jednostavnu aplikaciju na istoj mašini (host i cilj se podudaraju) koristeći gdbserver za simulaciju udaljenog scenarija.

Prvo napišete i kompajlirate mali programNa primjer, glupa petlja koja ispisuje brojač:

Naredba: gcc -g foo.c -o foo

Ključna stvar ovdje je zastava -gOvo dodaje potrebne informacije za otklanjanje grešaka binarnoj datoteci tako da gdb može prikazati linije koda, imena varijabli, tipove itd. U "pravom" okruženju za unakrsno kompajliranje, ovu kompajlaciju biste uradili pomoću cross-toolchaina, a zatim kopirali i binarnu datoteku i njene zavisnosti na cilj.

Sljedeći korak je pokretanje gdbservera na ciljnom serveru.Ako su host i target ista mašina, onda:

Naredba: gdbserver localhost:3333 foo

Vidjet ćete poruku sličnu „Proces foo kreiran; pid = XXXX; Osluškuje se port 3333“. Ovo ukazuje na to da je gdbserver kreirao proces i čeka da se gdb poveže. Ako ste na sistemu gdje su potrebne dodatne privilegije (na primjer, za povezivanje sa sistemskim procesima), možda ćete morati pokrenuti naredbu sa sudoAli uvijek je mudro biti oprezan prilikom davanja dozvole. korijen do desumporizatora.

Na hostu pokrećete gdb specificirajući lokalnu izvršnu datoteku (isti onaj koji se izvršava na cilju ili identična kopija sa simbolima):

Naredba: gdb foo

Jednom kada uđete u gdb, uspostavljate udaljenu vezu sa:

Naredba: target remote localhost:3333

U tom trenutku, gdb učitava simbole iz lokalne binarne datoteke.Sinhronizira se sa gdbserverom i preuzima kontrolu nad procesom koji se zapravo izvršava pod gdbserverom. Odatle je tok uobičajen: komande poput break postaviti prelomne tačke, continue, step, next, print da pregledaju varijable, backtrace da vidim bateriju itd.

Povezivanje s pokrenutim procesima pomoću gdbservera

Ne želite uvijek pokrenuti program od nule.Često ste zainteresirani za pridruživanje procesu koji je već u toku (na primjer, httpd a rutersistemski demon ili produkcijska usluga).

Tipičan obrazac je korištenje opcije --attach sa gdbserveraprosljeđujući port na kojem će slušati i PID ciljnog procesa. Na primjer, na ruteru na koji ste kopirali gdbserver kompajliran za njegovu arhitekturu, mogli biste učiniti:

Naredba: gdbserver localhost:3333 --attach <pid_de_httpd>

Na strani hosta, koristit ćete verziju gdb-a koja podržava arhitekturu rutera., na primjer gdb-multiarchprethodno konfiguriranje arhitekture i endianness-a:

Naredba: set arch mips
set endian big

Zatim navodite lokalnu datoteku koja sadrži simbole. udaljenog binarnog programa (na primjer file httpd) i, ako je potrebno, kažete gdb-u gdje se binarna datoteka zapravo izvršava na ciljnoj lokaciji sa set remote exec-file /usr/bin/httpdKonačno, baš kao i prije, povezujete se sa:

Naredba: target remote 192.168.0.1:3333

Nakon što je pričvršćenMožete postaviti tačke prekida na određene funkcije (na primjer break checkFirmware), nastaviti izvršavanje i pustiti da normalan tok programa (na primjer, učitavanje firmvera s web sučelja) aktivira tačku prekida.

Korištenje gdbservera sa WinDbg-om na Linuxu

Posljednjih godina Microsoft je dodao podršku za otklanjanje grešaka u Linux procesima u WinDbg-u. Korištenje gdbservera kao pozadinskog okruženja. Ova funkcionalnost je namijenjena scenarijima u kojima radite u Windowsu, ali se kod izvršava na Linuxu (uključujući WSL).

Za otklanjanje grešaka u određenom Linux procesu pomoću WinDbg-a koristeći gdbserverTok bi bio otprilike ovakav: prvo locirate ciljni proces na Linux mašini pomoću komande poput ps -A (na primjer a python3 koji se izvršava), zatim pokrećete gdbserver na ciljnom serveru:

Naredba: gdbserver localhost:1234 python3

Ako okruženje to zahtijeva, možda ćete morati koristiti sudo gdbserver ...uz iste sigurnosne mjere kao i uvijek. Nakon što gdbserver označi da "Sluša na portu 1234", u WinDbg-u idite na "Datoteka / Poveži se sa udaljenim debuggerom" i navedite niz za povezivanje sljedećeg tipa:

Naredba: gdb:server=localhost,port=1234

WinDbg koristi mali "drajver" gdb protokola za komunikaciju sa gdbserverom i, kada se veza uspostavi, ostaje zaustavljena na tački boot procesa. Odatle možete koristiti njegove prozore steka, module, memoriju, tačke prekida, kao i naredbe poput k da vidite bateriju ili lm za popis modula (imajući na umu da neke naredbe očekuju PE format, a ne ELF, tako da u određenim slučajevima mogu prikazati čudne podatke).

gdbserver i WinDbg procesni server

Pored slučaja sa jednim procesom, WinDbg se može povezati sa gdbserverom koji djeluje kao procesni server. da radi sličnije načinu na koji radi sa udaljenim Windows procesima. U ovom režimu, gdbserver se pokreće sa --multi i bez povezanog procesa:

  Najbolji način za aktiviranje načina rada niske potrošnje na iPhoneu

Naredba: sudo gdbserver --multi localhost:1234

Iz WinDbg-a odaberite "Datoteka / Poveži se sa procesnim serverom" i ponovo koristite niz za povezivanje gdb:server=localhost,port=1234Kada je veza aktivna, možete navesti dostupne Linux procese i povezati se s onim koji želite ili čak pokrenuti novi proces.

Treba imati na umu jedan suptilan detalj.WinDbg razlikuje "procesni server" i "jedan cilj" ovisno o tome da li je gdbserver već povezan s procesom kada se poveže. Ako ste ostavili gdbserver povezan s procesom, zatvorili WinDbg, a zatim pokušali ponovo povezati, možda neće biti detektiran kao procesni server i možda ćete morati ponovo pokrenuti gdbserver.

Za završetak sesije procesnog serveraObično je dovoljno jednostavno pritisnuti CTRL+D u konzoli gdje je pokrenut gdbserver i zaustaviti debugiranje iz WinDbg-a. U nekim ekstremnim slučajevima, ako postoje problemi sa sinhronizacijom, možda će biti potrebno potpuno zatvoriti debugger i ponovo pokrenuti gdbserver od nule.

Upravljanje simbolima i izvornim kodom pri udaljenom otklanjanju grešaka

Jedan od ključeva za praktično udaljeno otklanjanje grešaka je dobro razlučivanje simbola i fontova.Bez simbola, navigacija kroz stek ili postavljanje tačaka prekida na određenim funkcijama postaje mučenje.

U klasičnim scenarijima gdb + gdbserver, idealno je čuvati kopiju izvršne datoteke sa simbolima na hostu. (neogoljeno) i izvorno stablo. gdb ne zahtijeva da udaljeni binarni fajl sadrži simbole; dovoljno je da lokalna datoteka koju učitavaš sa file podudara se s udaljenom izvršnom datotekom na nivou offseta.

U svijetu WinDbg-a i Linux debugginga, pojavili su se i servisi poput DebugInfoD-a.koji otkrivaju simbole i fontove preko HTTP-a. WinDbg može koristiti posebne putanje tipa DebugInfoD*https://debuginfod.elfutils.org obojica .sympath kao u .srcpath za preuzimanje DWARF simbola na zahtjev i izvornog koda Linux ELF binarnih datoteka.

U konkretnom primjeru sa WSL-om, gdje se korisnički kod nalazi ispod C:\Users\Bob\Mogli biste reći WinDbg-u:

Naredba: .sympath C:\Users\Bob\
.srcpath C:\Users\Bob\

A ako želite koristiti i DebugInfoD za sistemske binarne datoteke:

Naredba: .sympath+ DebugInfoD*https://debuginfod.elfutils.org
.srcpath+ DebugInfoD*https://debuginfod.elfutils.org

S ovom konfiguracijom, kada pregledate stek ili unesete libc funkcijeWinDbg može pokušati preuzeti odgovarajuće DWARF simbole i, ako server također otkrije kod, prikazati izvorni kod sa znatnim detaljima, iako interno Windows alatni lanac ne obrađuje ELF i DWARF tako "izvorno" kao PE i PDB.

Praktičan primjer: debugiranje C++ programa pomoću gdbserver-a i WinDbg-a

Ilustrativan primjer je mala C++ aplikacija koja ispisuje pozdrav na ekran., kompajliran u WSL-u sa simbolima za otklanjanje grešaka. Zamislite program koji rezerviše std::array<wchar_t, 50> i kopira dužu poruku u nju, što uzrokuje skraćivanje teksta i pojavljivanje znakova ???? na kraju

Nakon kompajliranja s nečim poput:

Naredba: g++ DisplayGreeting.cpp -g -o DisplayGreeting

Pokrećete gdbserver protiv tog binarnog fajla.:

Naredba: gdbserver localhost:1234 DisplayGreeting

U WinDbg-u se povezujete sa stringom gdb:server=localhost,port=1234 I, kada se sesija uspostavi i putanje simbola i fontova budu konfigurisane, postavljate tačku prekida u DisplayGreeting!mainmožete koristiti dx greeting da se pregleda lokalni niz i vidi njegova veličina (50 pozicija), te vizualno provjeri u kartici memorije ili u prikazu varijabli kako je pozdrav odsječen.

Ljepota ovog primjera je u tome što pokazuje da, čak i bez pune podrške za sve ELF/DWARF formate u WinDbg-uMožete pregledavati stekove, pregledavati tipove, postavljati tačke prekida prema imenu funkcije i relativno udobno se kretati kroz C++ kod koristeći gdbserver kao udaljeni backend.

Debagovanje Linux kernela pomoću qemu i gdb

gdbserver se ne koristi samo u korisničkom režimu; postoje i vrlo moćni scenariji u kernel režimu.posebno kada kombinujete QEMU sa podrškom za debugiranje. Iako ovdje ulogu "gdbservera" ispunjava QEMU-ova vlastita opcija, pristup je identičan: jedan kraj pokreće sistem koji se debuguje i otvara gdb port; drugi kraj je ili gdb ili debugger koji govori udaljenim protokolom.

Da biste debagovali kernel, potrebno ga je kompajlirati sa specifičnim opcijama za debagovanje.: aktiviranje generiranja informacija za otklanjanje grešaka (CONFIG_DEBUG_INFO), GDB kernel skripte (CONFIG_GDB_SCRIPTS) i vlastiti način otklanjanja grešaka kernela (CONFIG_DEBUG_KERNELTakođer je važno onemogućiti opcije koje uklanjaju simbole tokom povezivanja, kao što je "Ukloni simbole generirane asemblerom tokom povezivanja".

Nakon kompajliranja dobit ćete binarnu datoteku vmlinux "nije ogoljelo"...koji ćete koristiti iz gdb-a. Također vam je potreban osnovni initramfs, koji možete generirati naredbom poput:

Naredba: mkinitramfs -o ramdisk.img

Zatim pokrećete QEMU s parametrima za otklanjanje grešaka.Tipičan primjer uključuje opciju -gdb tcp::1234 da otvorite gdb-kompatibilnu udaljenu krajnju tačku i -S tako da virtuelna mašina počne pauzirana od početka. Također navodite kernel sa -kernel vmlinux, el -initrd ramdisk.img, memorija sa -m 512 i obično preusmjeravate konzolu na ttyS0 upravljati svime od terminal.

  Kako ažurirati Edge na najnoviju verziju na Windowsu 11: kompletan vodič korak po korak

Sa pritvorenim QEMU-om koji čeka gdbSa host računara, pokrećete gdb koji pokazuje na vmlinux i povezujete se sa target remote localhost:1234Odatle možete postaviti rane tačke prekida, na primjer hb start_kerneli kontrolisati izvršenje pomoću naredbi kao što su c (nastavi) i CTRL+C za ponovnu pauzu.

Nedavne promjene i nijanse u gdb-u i gdbserver-u

U modernim distribucijama poput Red Hat Enterprise Linuxa 8, postoji niz promjena u gdb i gdbserver koje vrijedi imati na umu.posebno ako dolazite s prethodnih verzija ili imate skripte koje analiziraju izlaz debuggera.

S jedne strane, gdbserver sada pokreće "niže" procese koristeći shellBaš kao i gdb, ovo omogućava proširenje i zamjene varijabli u komandnoj liniji. Ako iz bilo kojeg razloga trebate onemogućiti ovo ponašanje, postoje posebne postavke dokumentirane u RHEL 8 za povratak na prethodni način rada.

Nekoliko stvari je također uklonjeno ili promijenjenopodrška za otklanjanje grešaka za Java programe kompajlirane sa gcj, HP-UX XDB kompatibilni način rada, naredbe kao što su set remotebaud (zamijenjeno sa set serial baud) ili kompatibilnost s određenim starijim formatom stabsNadalje, numeriranje navoja više nije globalno, već po "donjem" navoju, i pojavljuje se kao inferior_num.thread_num, s novim praktičnim varijablama kao što su $_gthread da se odnosi na globalni identifikator.

Još jedna relevantna nova funkcija je podešavanje max-value-sizeOvo ograničava količinu memorije koju gdb može dodijeliti za prikaz sadržaja vrijednosti. Zadana vrijednost je 64 KiB, tako da pokušaji ispisa ogromnih nizova ili masivnih struktura mogu rezultirati upozorenjem "vrijednost je prevelika" umjesto prikaza sve dostupne memorije.

Također je prilagođen način na koji gdb rukuje sysrootZadana vrijednost je sada target:To znači da će za udaljene procese prvo pokušati pronaći biblioteke i simbole na ciljnom sistemu. Ako želite da se prioritet da lokalnim simbolima, trebali biste pokrenuti set sysroot sa rutom koja vas zanima prije nego što krenete target remote.

Što se tiče historije komandi, varijabla okruženja koja se sada koristi je GDBHISTSIZE umesto HISTSIZEOvo vam omogućava da precizno podesite koliko dugo želite zadržati komande koje ste upisali u sesijama otklanjanja grešaka, a da pritom ne ometate ponašanje drugih aplikacija koje koriste biblioteku za čitanje linija.

Savjeti za radni tok i rješavanje problema s gdbserverom

Za ugodan tijek rada, postoje neki obrasci koji obično vrlo dobro funkcioniraju. Prilikom razvoja za ugrađene sisteme ili udaljene servere, prvi korak je što veća automatizacija kompajliranja simbola i binarnog implementacije na cilj. Na ovaj način, uvijek znate koja verzija izvršne datoteke se izvršava i imate kopiju simbola lako dostupnu na hostu.

U okruženjima s mnogo jezgara koje uzrokuju pad sistema, vrijedi naučiti kako koristiti gdb u batch modu., sa zastavama poput --batch, --ex y -x za automatsko pokretanje naredbi na listi jezgara i obradu njihovih povratnih tragova iz skripti (na primjer u pitonOvo vam omogućava da brzo filtrirate ponovljene probleme, grupišete greške po tragu steka itd.

Kada nešto pođe po zlu s udaljenom vezom, opcija --debug gdbserver je tvoj najbolji prijateljAko pokrenete, na primjer, procesni server sa:

Naredba: gdbserver --debug --multi localhost:1234

Konzola gdbserver-a će prikazati detaljne tragove onoga što se dešava Na nivou udaljenog protokola, ovo uključuje dolazne pakete, greške u formatiranju, probleme s prekidom veze itd. Ovo je vrlo korisno kada se vaš gdb server iznenada prekine veza, proces se sruši čim se postavi tačka prekida ili vaš debug GUI pošalje nešto što gdbserver ne razumije.

U kontekstima kao što je TP-Link ruter gdje povezujete gdbserver sa kritičnim procesom kao što je httpdRelativno je uobičajeno da određene tačke prekida stvaraju uslove utrke ili nadzorne funkcije (watchdog) koje prekidaju proces kada on predugo ostane "zaglavljen" u debuggeru. U tim situacijama može biti potrebno prilagoditi koji su signali blokirani, koje niti su kontrolirane i, ako je primjenjivo, izmijeniti samu konfiguraciju sistema (vremena čekanja, hardverske nadzorne funkcije) kako bi se omogućile duže sesije debugiranja.

Dobro korištenje gdbservera uključuje kombinovanje nekoliko dijelovaKompajlirajte s odgovarajućim simbolima, odaberite ispravan gdb za arhitekturu, konfigurirajte putanje simbola i izvora, shvatite dva glavna načina rada gdbservera (jednoprocesni i višeprocesni) i ne bojte se izvući iz tog načina rada. --debug kada se veza ne ponaša kako se očekuje. S tom osnovom, otklanjanje grešaka u aplikacijama koje se izvršavaju na udaljenom Linux sistemu, ruteru ili virtuelnoj mašini sa prilagođenim kernelom sa vašeg računara postaje prilično rutinsko i, prije svega, nevjerovatno korisno.