Sådan bruger du gdbserver til fjernfejlfinding på Linux

Sidste ændring: 14/01/2026
Forfatter: Isaac
  • gdbserver fungerer som en fjernagent for GDB til at styre processer på en anden maskine via TCP eller seriel.
  • For at fejlfinde eksternt er det vigtigt at kompilere med symbolerBrug den passende gdb og konfigurer symbol- og skrifttypestier korrekt.
  • gdbserver tilbyder enkeltproces- og flerprocestilstand og integrerer også med WinDbg og QEMU til kernel-fejlfinding.
  • Valgmuligheder som --debug, sysroot og value size limits hjælper med at diagnosticere problemer og stabilisere sessioner.

Fjernfejlfinding med gdbserver

Hvis du programmerer i C eller C++ Linux og du har aldrig rørt gdbserverDu går glip af et af de mest nyttige værktøjer til fjernfejlfinding af processer, uanset om det er på en server, et indlejret system eller endda i en virtuel maskine eller WSL. Langt fra at være noget "magisk" eller forbeholdt eksperter, er gdbserver blot et lille program, der kommunikerer med gdb og styrer udførelsen af ​​målprocessen.

Hovedideen er meget enkel.: på den maskine, hvor den binære fil, du vil fejlsøge, kører (den mål) du starter gdbserver; på din arbejdscomputer (den hostDu starter gdb eller endda WinDbg med understøttelse af gdb-protokollen. Begge opretter forbindelse via TCP eller en seriel port, og derfra kan du indstille breakpoints, inspicere variabler, se stakken eller følge udførelsen trin for trin, som om programmet kørte på din egen maskine.

Hvad er gdbserver, og hvornår giver det mening at bruge det?

Hvad er gdbserver

gdbserver er en fjernfejlfindings-"agent" for GNU gdbDens funktion er meget specifik: den kører på den maskine, hvor det program, der skal analyseres, kører, styrer den proces (eller processer) og kommunikerer med en gdb-klient, der er placeret på en anden maskine (eller på den samme) via en fjernforbindelse.

I daglig brug bruges gdbserver i to typiske scenarierFejlfindingssoftware, der kører i indlejrede miljøer (routere, boards med afkortet Linux, enheder) IoTosv.) og fejlfindingsprocesser på eksterne Linux-maskiner, hvor det ikke er praktisk eller simpelthen ikke muligt at have en "fed" gdb med alle bibliotekerne og symbolerne.

På et praktisk plan håndterer gdbserver opgaver som f.eks. Læs og skriv procesregistre og hukommelse, kontroller udførelse (fortsæt, pause, trinvis gennemgang), administrer breakpoints og send alle disse data til gdb ved hjælp af GDB-fjernprotokollen. Denne filosofi minder meget om værktøjer som OpenOCD, der fungerer som en bro mellem gdb og en hardware ekstern, med den forskel at gdbserver kører på det samme system som den binære fil.

Hvis du kommer fra miljøer Windows Det er også interessant at vide Fejlfindingsprogrammer som WinDbg kan kommunikere med en gdbserver på Linux, så du kan fejlfinde brugerprocesser på Linux fra WinDbg ved hjælp af fjernfejlfindingssupport via gdb-protokollen, som Microsoft har indarbejdet i nyere versioner.

Grundlæggende krav til fejlfinding med gdb og gdbserver

Krav til brug af gdbserver

Før du starter med fjernfejlfinding, skal du forstå vært/mål-forholdet.. Den mål Det er den maskine, hvor det program, der skal fejlfindes, kører, og hvor gdbserver vil blive udført; host Dette er den maskine, hvorfra du skal køre gdb (eller WinDbg), og hvor du vil have kildekoden og helst fejlfindingssymbolerne.

Det væsentlige udgangspunkt er at kompilere den binære fil med symbolerI GCC eller g++ opnås dette med flaget -gog det er normalt tilrådeligt også at deaktivere optimeringer (for eksempel med -O0Dette gør det muligt for debuggeren at vise variabler, makroer og kodestruktur mere præcist. For specifikke makroer kan du bruge højere debuggingniveauer, f.eks. -g3.

På værtssiden skal du bruge en kompatibel version af gdb med målarkitekturen. For at debugge et MIPS-, ARM- eller andet indlejret system med arkitektur, skal du bruge gdb'en for den tilsvarende cross-toolchain (for eksempel) arm-none-eabi-gdb o gdb-multiarch) og, om nødvendigt, konfigurer arkitekturen og endianness med kommandoer som set arch y set endian.

Med hensyn til forbindelsen understøtter gdbserver to hovedtyperEt serielt link (meget almindeligt i indlejret hardware, via UART) og TCP/IP, hvilket er mest praktisk, når målet er på det samme netværk eller er en Linux-maskine, der er tilgængelig over netværket. I begge tilfælde bruges kommandoen fra gdb. target remote for at oprette forbindelse til det slutpunkt, der er eksponeret af gdbserver.

Måder at starte gdbserver på: enkeltproces- og flerprocestilstand

gdbserver-udførelsestilstande

gdbserver kan fungere på to hovedmåder Når vi taler om brugertilstandsfejlfinding: direkte forbundet med en enkelt proces eller som en "processerver", der tillader listeføring og tilknytning til forskellige systemprocesser.

I enkeltprocestilstand Du starter gdbserver og angiver host:port og det program, der skal køres. I et simpelt eksempel på en Linux-desktopmaskine kan du gøre noget i retning af dette:

kommando: gdbserver localhost:3333 foo

Med den kommando starter gdbserver den binære fil. foo og han bliver ved med at lytte på port 3333Indtil en fjern gdb opretter forbindelse, forbliver programmet stoppet; når gdb opretter forbindelse til target remote localhost:3333, processen begynder at blive styret af descrusheren.

I multiprocestilstand (processerver) bruges indstillingen --multiI dette tilfælde starter gdbserver ikke direkte noget program, men lytter blot efter indgående forbindelser og tillader klienten (gdb eller WinDbg) at styre, hvilken proces der skal oprettes eller tilknyttes:

  Google lancerer Gemini Code Assist: den gratis AI-drevne programmeringsassistent

kommando: gdbserver --multi localhost:1234

Når man arbejder med WinDbg på Linux, er denne multitilstand særligt interessant.Fordi du fra WinDbg selv kan liste processer på fjernsystemet, se PID, bruger og kommandolinje, og knytte til den, du er interesseret i, på samme måde som det gøres med processerveren. dbgsrv.exe på Windows.

Fjernfejlfinding med gdbserver og gdb trin for trin

Lad os bringe det ned til jorden med et meget typisk eksempel.Fejlfind en simpel applikation på den samme maskine (vært og mål matcher) ved hjælp af gdbserver til at simulere fjernscenariet.

Først skriver og kompilerer du et lille programFor eksempel en fjollet løkke, der udskriver en tæller:

kommando: gcc -g foo.c -o foo

Nøglen her er flaget -gDette tilføjer de nødvendige fejlfindingsoplysninger til den binære fil, så gdb kan vise kodelinjer, variabelnavne, typer osv. I et "rigtigt" krydskompileringsmiljø ville du udføre denne kompilering med cross-toolchain og derefter kopiere både den binære fil og dens afhængigheder til målet.

Det næste trin er at starte gdbserver på destinationenHvis vært og destination er den samme maskine, så:

kommando: gdbserver localhost:3333 foo

Du vil se en besked, der ligner “Process foo created; pid = XXXX; Listening on port 3333”. Dette indikerer, at gdbserver har oprettet processen og venter på, at gdb opretter forbindelse. Hvis du er på et system, hvor der kræves flere rettigheder (f.eks. for at oprette forbindelse til systemprocesser), skal du muligvis køre kommandoen med sudoMen det er altid klogt at være forsigtig, når man giver tilladelse. rod til afsvovlereren.

På værten starter du gdb med at angive den lokale eksekverbare fil (den samme som kører på målet, eller en identisk kopi med symboler):

kommando: gdb foo

Når du er inde i gdb, etablerer du fjernforbindelsen med:

kommando: target remote localhost:3333

På det tidspunkt indlæser gdb symbolerne fra den lokale binære fil.Den synkroniserer med gdbserver og tager kontrol over den proces, der rent faktisk kører under gdbserver. Derfra er flowet det sædvanlige: kommandoer som break at sætte brudpunkter, continue, step, next, print at inspicere variabler, backtrace for at se batteriet osv.

Forbinder til kørende processer med gdbserver

Du har ikke altid lyst til at starte programmet fra bunden.Ofte er du interesseret i at deltage i en proces, der allerede kører (for eksempel en httpd en routeren systemdæmon eller en produktionstjeneste).

Det typiske mønster er at bruge indstillingen --attach fra gdbservervideregiver porten, hvor den vil lytte, og PID'en for målprocessen. For eksempel, på en router, hvor du har kopieret en gdbserver, der er kompileret til dens arkitektur, kan du gøre:

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

På værtssiden skal du bruge en version af gdb, der understøtter routerens arkitektur., for eksempel gdb-multiarchkonfigurere arkitekturen og endianness på forhånd:

kommando: set arch mips
set endian big

Derefter angiver du den lokale fil, der indeholder symbolerne. af den eksterne binære fil (for eksempel file httpd) og, om nødvendigt, fortæller du gdb, hvor den binære fil rent faktisk kører på målet med set remote exec-file /usr/bin/httpdTil sidst, ligesom før, opretter du forbindelse til:

kommando: target remote 192.168.0.1:3333

Når den er fastgjortDu kan indstille breakpoints på specifikke funktioner (f.eks. break checkFirmware), fortsæt udførelsen og lad programmets normale flow (f.eks. upload af firmware fra webgrænsefladen) udløse breakpointet.

Brug af gdbserver med WinDbg på Linux

I de senere år har Microsoft tilføjet understøttelse af fejlfinding af Linux-processer i WinDbg. Brug af gdbserver som backend. Denne funktionalitet er beregnet til scenarier, hvor du arbejder i Windows, men koden kører på Linux (inklusive WSL).

Sådan fejlsøger du en specifik Linux-proces med WinDbg ved hjælp af gdbserverProcessen ville være nogenlunde sådan her: først finder du målprocessen på Linux-maskinen med en kommando som ps -A (for eksempel en python3 som kører), så starter du gdbserver på målet:

kommando: gdbserver localhost:1234 python3

Hvis miljøet kræver det, kan du være nødt til at bruge sudo gdbserver ...med de samme sikkerhedsforanstaltninger som altid. Når gdbserver angiver, at den "Lytter på port 1234", skal du i WinDbg gå til "Fil / Opret forbindelse til fjernfejlfinder" og angive en forbindelsesstreng af følgende type:

kommando: gdb:server=localhost,port=1234

WinDbg bruger en lille gdb-protokol-"driver" til at kommunikere med gdbserver. og når forbindelsen er etableret, forbliver den stoppet på det punkt, hvor støvle af processen. Derfra kan du bruge dens stakvinduer, moduler, hukommelse, breakpoints samt kommandoer som k for at se batteriet eller lm at liste moduler (husk at nogle kommandoer forventer PE-format og ikke ELF, så de kan vise mærkelige data i visse tilfælde).

gdbserver og WinDbg-processerver

Ud over enkeltprocestilfældet kan WinDbg oprette forbindelse til en gdbserver, der fungerer som en processerver. at fungere mere på samme måde som med eksterne Windows-processer. I denne tilstand startes gdbserver med --multi og uden en tilhørende proces:

  Den bedste måde at aktivere lavenergitilstand på iPhone

kommando: sudo gdbserver --multi localhost:1234

Fra WinDbg skal du vælge "Fil / Opret forbindelse til processerver" og du genbruger forbindelsesstrengen gdb:server=localhost,port=1234Når forbindelsen er aktiv, kan du liste de tilgængelige Linux-processer og vedhæfte dem til den, du ønsker, eller endda starte en ny proces.

En subtil detalje skal huskes.WinDbg skelner mellem "processerver" og "enkelt mål" afhængigt af, om gdbserver allerede er knyttet til en proces, når den opretter forbindelse. Hvis du har ladet gdbserver være knyttet til en proces, lukket WinDbg og derefter forsøgt at genoprette forbindelsen, bliver den muligvis ikke registreret som en processerver, og du skal muligvis genstarte gdbserver.

Sådan afslutter du en processerversessionNormalt er det tilstrækkeligt blot at trykke på CTRL+D i konsollen, hvor gdbserver kører, og stoppe fejlfinding fra WinDbg. I nogle ekstreme tilfælde, hvis der er synkroniseringsproblemer, kan det være nødvendigt at lukke fejlfindingsprogrammet helt og genstarte gdbserver fra bunden.

Symbol- og kildekodehåndtering i fjernfejlfinding

En af nøglerne til at gøre fjernfejlfinding praktisk er at have symbol- og skrifttypedelen velopløstUden symboler bliver det tortur at navigere i stakken eller indstille breakpoints på specifikke funktioner.

I klassiske gdb + gdbserver-scenarier er det ideelt at beholde en kopi af den eksekverbare fil med symboler på værten. (ikke-strippet) og kildekoden. gdb kræver ikke, at den eksterne binære fil indeholder symbolerne; det er tilstrækkeligt, at den lokale fil, du indlæser med file match den eksterne eksekverbare fil på offset-niveau.

I WinDbg- og Linux-fejlfindingsverdenen er der også dukket tjenester som DebugInfoD op.som eksponerer symboler og skrifttyper via HTTP. WinDbg kan bruge særlige stier af typen DebugInfoD*https://debuginfod.elfutils.org både .sympath som i .srcpath for at downloade DWARF-symboler og Linux ELF-binære kildekode on-demand.

I et specifikt eksempel med WSL, hvor brugerkoden er under C:\Users\Bob\Du kunne fortælle WinDbg:

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

Og hvis du også vil bruge DebugInfoD til systembinære filer:

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

Med denne konfiguration, når du inspicerer stakken eller indtaster libc-funktionerWinDbg kan forsøge at downloade de tilsvarende DWARF-symboler, og hvis serveren også eksponerer koden, vise kildekoden i betydelig detalje, selvom Windows-værktøjskæden internt ikke håndterer ELF og DWARF lige så "native" som PE og PDB.

Praktisk eksempel: fejlfinding af et C++-program med gdbserver og WinDbg

Et illustrativt eksempel er et lille C++-program, der skriver en hilsen til skærmen., kompileret i WSL med debugging-symboler. Forestil dig et program, der reserverer en std::array<wchar_t, 50> og kopierer en længere besked ind i den, hvilket får teksten til at blive afkortet, og der vises tegn ???? i slutningen

Efter at have kompileret med noget i retning af:

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

Du starter gdbserver mod den binære fil:

kommando: gdbserver localhost:1234 DisplayGreeting

I WinDbg forbinder du med strengen gdb:server=localhost,port=1234 Og når sessionen er etableret, og symbol- og skrifttypestier er konfigureret, angiver du et breakpoint i DisplayGreeting!maindu kan bruge dx greeting at inspicere det lokale array og se dets størrelse (50 positioner) og visuelt kontrollere i hukommelsesfanen eller i variabelvisningen, hvordan hilsenen afbrydes.

Det smukke ved dette eksempel er, at det demonstrerer, at selv uden fuld understøttelse af alle ELF/DWARF-formater i WinDbgDu kan navigere i stakke, inspicere typer, indstille breakpoints efter funktionsnavn og navigere rimelig komfortabelt gennem C++-kode ved at bruge gdbserver som en fjern backend.

Fejlfinding af Linux-kernen med qemu og gdb

gdbserver bruges ikke kun i brugertilstand; der er også meget kraftfulde scenarier i kernetilstand.især når man kombinerer QEMU med debugging-support. Selvom rollen som "gdbserver" her opfyldes af QEMUs egen indstilling, er fremgangsmåden identisk: den ene ende kører det system, der skal debugges, og åbner en gdb-port; den anden ende er enten gdb eller en debugger, der taler den eksterne protokol.

For at fejlfinde kernen skal du kompilere den med specifikke fejlfindingsindstillinger.: aktiver generering af fejlfindingsoplysninger (CONFIG_DEBUG_INFO), GDB-kerneskripterne (CONFIG_GDB_SCRIPTS) og kernens egen fejlfindingstilstand (CONFIG_DEBUG_KERNELDet er også vigtigt at deaktivere indstillinger, der fjerner symboler under linkning, såsom "Fjern assembler-genererede symboler under linkning".

Efter kompilering får du en binær fil vmlinux "ikke strippet"hvilket er den du skal bruge fra gdb. Du skal også bruge en grundlæggende initramfs, som du kan generere med en kommando som:

kommando: mkinitramfs -o ramdisk.img

Så starter du QEMU med debugging-parametreEt typisk eksempel inkluderer muligheden -gdb tcp::1234 at åbne et gdb-kompatibelt fjerntliggende slutpunkt, og -S så den virtuelle maskine starter pauset fra starten. Du angiver også kernen med -kernel vmlinux, The -initrd ramdisk.img, hukommelsen med -m 512 og du omdirigerer normalt konsollen til ttyS0 at styre alt fra terminal.

  Sådan opdaterer du Edge til den nyeste version på Windows 11: en komplet trin-for-trin guide

Med QEMU tilbageholdt i afventning af gdbFra værtsmaskinen starter du gdb med at pege på vmlinux og du forbinder dig med target remote localhost:1234Derfra kan du indstille tidlige breakpoints, for eksempel en hb start_kernelog kontroller udførelsen med kommandoer som f.eks. c (fortsæt) og CTRL+C for at sætte på pause igen.

Seneste ændringer og nuancer i gdb og gdbserver

I moderne distributioner som Red Hat Enterprise Linux 8 er der en række ændringer i gdb og gdbserver, som er værd at huske på.især hvis du kommer fra tidligere versioner eller har scripts, der analyserer debugger-outputtet.

På den ene side starter gdbserver nu de "nederste" processer ved hjælp af en shellLigesom gdb tillader dette variabeludvidelse og -substitutioner på kommandolinjen. Hvis du af en eller anden grund har brug for at deaktivere denne funktion, er der specifikke indstillinger dokumenteret i RHEL 8 for at vende tilbage til den forrige tilstand.

Flere ting er også blevet fjernet eller ændret: debugging-support for Java-programmer kompileret med gcj, HP-UX XDB-kompatibilitetstilstanden, kommandoer som f.eks. set remotebaud (erstattet af set serial baud) eller kompatibilitet med et bestemt ældre format af stabsDesuden er trådnummereringen ikke længere global, men efter "nederste" tråd, og vises som inferior_num.thread_num, med nye bekvemmelighedsvariabler som f.eks. $_gthread at henvise til den globale identifikator.

En anden relevant ny funktion er justeringen max-value-sizeDette begrænser mængden af ​​hukommelse, som gdb kan allokere til at vise indholdet af en værdi. Standardværdien er 64 KiB, så forsøg på at udskrive store arrays eller massive strukturer kan resultere i en "værdi for stor"-advarsel i stedet for at vise al tilgængelig hukommelse.

Det er også blevet justeret, hvordan gdb håndterer sysrootStandardværdien er nu target:Det betyder, at den for eksterne processer først vil forsøge at finde biblioteker og symboler på målsystemet. Hvis du vil have den til at prioritere lokale symboler, skal du køre set sysroot med den rute, der interesserer dig, før du tager den target remote.

Med hensyn til kommandohistorikken er den miljøvariabel, der nu bruges GDBHISTSIZE i stedet for HISTSIZEDette giver dig mulighed for at finjustere, hvor længe du vil beholde de kommandoer, du har skrevet i fejlfindingssessioner, uden at forstyrre andre programmers funktionsmåde, der bruger linjelæsningsbiblioteket.

Tips til arbejdsgange og fejlfinding med gdbserver

For at have en behagelig arbejdsgang er der nogle mønstre, der har tendens til at fungere rigtig godt. Når man udvikler til indlejrede systemer eller eksterne servere, er det første skridt at automatisere symbolkompilering og binær implementering til målet så meget som muligt. På denne måde ved man altid, hvilken version af den eksekverbare fil der kører, og har symbolkopien let tilgængelig på værten.

I miljøer med mange crashkerner er det værd at lære, hvordan man bruger gdb i batch-tilstand.med flag som --batch, --ex y -x at automatisk starte kommandoer på en liste over kerner og behandle deres backtraces fra scripts (for eksempel i PythonDette giver dig mulighed for hurtigt at filtrere gentagne problemer fra, gruppere fejl efter stakspor osv.

Når noget går galt med fjernforbindelsen, vises indstillingen --debug gdbserver er din bedste venHvis du for eksempel starter en processerver med:

kommando: gdbserver --debug --multi localhost:1234

gdbserver-konsollen vil vise detaljerede spor af, hvad der sker På fjernprotokolniveau inkluderer dette indgående pakker, formateringsfejl, afbrydelsesproblemer osv. Dette er meget nyttigt, når din gdb-server pludselig afbryder forbindelsen, en proces går ned, så snart et breakpoint er angivet, eller din debug GUI sender noget, som gdbserver ikke forstår.

I sammenhænge som en TP-Link router, hvor du forbinder gdbserver til en kritisk proces som f.eks. httpdDet er relativt almindeligt, at visse breakpoints skaber race conditions eller watchdogs, der dræber processen, når den forbliver "fastlåst" for længe i debuggeren. I disse situationer kan det være nødvendigt at justere, hvilke signaler der blokeres, hvilke tråde der styres, og, hvis det er relevant, ændre selve systemkonfigurationen (timeout-tider, hardware watchdogs) for at tillade længere debugging-sessioner.

God brug af gdbserver involverer at kombinere flere deleKompilér med passende symboler, vælg den korrekte gdb til arkitekturen, konfigurer symbol- og kildestier, forstå de to hovedtilstande i gdbserver (single-proces og multi-proces), og vær ikke bange for at trække fra tilstanden. --debug når forbindelsen ikke opfører sig som forventet. Med det grundlag bliver fejlfinding af applikationer, der kører på et fjerntliggende Linux-system, en router eller en virtuel maskine med en brugerdefineret kerne fra din pc, ret rutinemæssig og frem for alt utrolig nyttig.