Linux élő távoli folyamat hibakeresése

Ez a cikk azt ismerteti, hogyan hozhat létre élő WinDbg-kapcsolatot Linuxhoz. A linuxos élő távoli folyamat hibakereséséhez a WinDbg 1.2402.24001.0-s vagy újabb verziója szükséges.

GNU Debugger - GDBServer Linuxon kerül használatra a WinDbg-kapcsolat támogatására. További információ a GDBServerről: https://en.wikipedia.org/wiki/Gdbserver. A távoli gdb-hibakeresés dokumentációját itt tekintheti meg - https://sourceware.org/gdb/current/onlinedocs/gdb#Remote-Debugging

Az itt látható példák a Windows alrendszert használják Linuxhoz (WSL), de más Linux-implementációk is használhatók.

A távoli folyamat hibakeresésének WinDbg-típusai

A WinDbg használatával történő távoli hibakeresésnek két elsődleges módszere van: egy folyamatkiszolgáló vagy egy KD kapcsolatkiszolgáló. A folyamatkiszolgálók a felhasználói módú hibakereséshez használatosak; A KD kapcsolatkiszolgálók kernel módú hibakereséshez használhatók. Ezekről a WinDbg-kapcsolattípusokról általános információt a Folyamatkiszolgálók (felhasználói mód) és a KD kapcsolatkiszolgálók (Kernel mód) című témakörben talál.

A Linux felhasználói módú folyamatok hibakeresésének két módja van. Elindíthatja a gdbservert egy adott folyamaton, vagy elindíthatja a gdbservert folyamatkiszolgálóként , amely listázhatja és csatolhatja a meglévő folyamatokat. Ez hasonlít a DbgSrv (dbgsrv.exe) folyamatkiszolgálóhoz Windows rendszeren. További információ: Folyamatkiszolgáló aktiválása.

Felhasználói módú Linux-folyamat hibakeresése

Egy adott egyfelhasználós vagy több módú folyamathoz csatlakozhat, ha az összes folyamatot egy listában látja, és kiválaszt egyet, amelyhez csatlakozni szeretne. Mindkét metódust ebben a témakörben ismertetjük. Mindkét metódus ugyanazzal a kapcsolati sztringszintaxissal rendelkezik, amelyet a következő szakaszban ismertetünk.

A gdbserver kapcsolati sztring formátuma

A gdbserverhez való csatlakozáshoz használt formátum a "protokoll:argumentumok", ahol az argumentumok az "argument=value" vesszővel tagolt listája. Felhasználói módú gdbserver-kapcsolat esetén a protokoll gdb, az argumentumok pedig a következők.

server=<address> - Kötelező: a gdbserver IP-címét jelzi, amelyhez csatlakozni szeretne.

port=<port> - Kötelező: a gdbserver portszámát jelzi, amelyhez csatlakozni szeretne.

threadEvents=<true|false> - Nem kötelező: azt jelzi, hogy a gdbserver ezen verziójának száleseményei helyesen működnek-e leállítási módban.

Az aktuális gdbserver-kiadásokban van egy probléma, amely miatt a szálesemények leállási módban történő engedélyezése (amelyet a WinDbg használ) a gdbserver összeomlását okozza. Ha ez az érték hamis (az alapértelmezett érték), a szálindítási és -leállítási események szintetizálva lesznek, de jelentősen később megjelenhetnek, mint a szállétrehozás/-megsemmisítés tényleges időpontja. Ha ez a javítás elérhető a gdbserverben, a tényleges események engedélyezhetők ezzel a beállítással.

Csatlakozás egyetlen felhasználói módú folyamathoz

Ez a szakasz azt ismerteti, hogyan azonosíthat és csatlakozhat egyetlen felhasználói módú folyamathoz Linuxon a WinDbg használatával.

WSL (Windows-alrendszer Linuxhoz)

Az itt látható példák a WSL-t (Linux windowsos alrendszerét) használják, de más Linux-implementációk is használhatók. A WSL beállításával és használatával kapcsolatos információkért lásd:

Válassza ki a kívánt folyamatot

A Linuxban futó folyamatok listázása a ps -A parancs használatával határozza meg a csatlakozni kívánt futó folyamatot.

user1@USER1:/mnt/c/Users/USER1$ ps -A
    PID TTY          TIME CMD
    458 pts/1    00:00:00 bash
    460 ?        00:00:00 rtkit-daemon
    470 ?        00:00:00 dbus-daemon
    482 ?        00:00:19 python3
   1076 ?        00:00:00 packagekitd
   1196 pts/0    00:00:00 ps

Ebben a példában bemutatjuk, hogy csatlakozunk a Python3-hoz.

A célrendszer IP-címének megkeresése

Ha távoli Linux-célhoz csatlakozik, használjon egy parancsot, például ip route showa külső IP-cím meghatározásához.

user1@USER1:/mnt/c/Users/USER1$ ip route show
default via 192.168.1.1 dev enp3s0 proto dhcp metric 100
172.25.144.0/24 dev enp3s0 proto kernel scope link src 192.168.1.107 metric 100

Ebben az útmutatóban az ugyanazon a számítógépen futó WSL-hez fogunk csatlakozni, és a localhost IP-címét fogjuk használni.

GDBServer csatolása a kijelölt folyamathoz

A linuxos WSL-konzolon adja meg gdbserver localhost:1234 python3 a gdbserver elindításához az 1234-es porton, és csatolja a python3-folyamathoz.

USER1@USER1:/mnt/c/Users/USER1$ gdbserver localhost:1234 python3
Process python3 created; pid = 1211
Listening on port 1234

Egyes Linux-környezetek esetében előfordulhat, hogy a parancsot rendszergazdaként kell futtatni, például a sudo - sudo gdbserver localhost:1234 python3használatával. Körültekintően engedélyezze a hibakereső rendszergazda legfelső szintű hozzáférését, és csak akkor használja ezt, ha szükséges.

A folyamatkiszolgáló-kapcsolat létrehozása a WinDbg-ben

Nyissa meg a WinDbg fájlt, és válassza a "Fájl / Csatlakozás távoli hibakeresőhöz" lehetőséget, és adjon meg egy protokollsztringet a kapcsolathoz. Ebben a példában a következőt fogjuk használni: gdb:server=localhost,port=1234.

Képernyőkép a WinDbg Start hibakeresési képernyőjéről, amelyen a kapcsolati sztring látható.

Miután az OK gombra kattint, a hibakeresőnek csatlakoznia kell a gdbserverhez, és az első folyamatindulási megszakításnál kell lennie.

Miután a kezdeti töréspontnál jár, többször is megnyomhatja a "g" gombot. Megkapja a modulbetöltési üzeneteket (és az sxe típusú "modulbetöltés megszakítása" események megfelelően működnek).

Vegye figyelembe, hogy a hibakeresési szimbólumok gyorsítótárba való betöltése eltarthat egy ideig. Amellett, hogy szimbólumokat és bináris fájlokat keres a szimbólumkiszolgálón vagy a helyi keresési útvonalon keresztül, a GDBServer integrációja képes lekérni ezeket a fájlokat a távoli fájlrendszerből, ha nem találhatók a symsrv-en vagy helyileg. Ez általában sokkal lassabb művelet, mint a szimszrv vagy egy helyi keresési útvonal szimbólumainak lekérése, de a megfelelő szimbólumok megkeresésével jobb élményt nyújt.

A k stacks paranccsal listázhatja a vermet. Python3-modulokat jelenít meg, így ez megerősíti, hogy a Python3 hibakeresése Linuxon a WinDbg használatával történik.

0:000> k
 # Child-SP          RetAddr               Call Site
00 00007fff`ffffce10 00007fff`f786d515     libc_so!_select+0xbd
01 00007fff`ffffce80 00005555`55601ce8     readline_cpython_310_x86_64_linux_gnu!PyInit_readline+0xac5
02 00007fff`ffffcf60 00005555`556f06a1     python3!PyOS_Readline+0x109
03 00007fff`ffffcfa0 00005555`556eee7e     python3!PyFrame_LocalsToFast+0x62a1
04 00007fff`ffffd000 00005555`556edcf0     python3!PyFrame_LocalsToFast+0x4a7e
05 00007fff`ffffdb80 00005555`557a18e9     python3!PyFrame_LocalsToFast+0x38f0
06 00007fff`ffffdc00 00005555`557a1470     python3!PyCodec_LookupError+0xb09
07 00007fff`ffffdc50 00005555`557b89dc     python3!PyCodec_LookupError+0x690
08 00007fff`ffffdc70 00005555`5560b42f     python3!PyUnicode_Tailmatch+0xc6c
09 00007fff`ffffdcb0 00005555`5560b012     python3!PyRun_InteractiveLoopObject+0x4e0
0a 00007fff`ffffdd50 00005555`557b7678     python3!PyRun_InteractiveLoopObject+0xc3
0b 00007fff`ffffdda0 00005555`555f55c8     python3!PyRun_AnyFileObject+0x68
0c 00007fff`ffffddd0 00005555`555ea6e8     python3!PyRun_AnyFileExFlags+0x4f
0d 00007fff`ffffde00 00005555`55780cad     python3!Py_str_to_int+0x2342a
0e 00007fff`ffffdef0 00007fff`f7c7cd90     python3!Py_BytesMain+0x2d
0f 00007fff`ffffdf20 00007fff`f7c7ce40     libc_so!_libc_init_first+0x90
10 00007fff`ffffdfc0 00005555`55780ba5     libc_so!_libc_start_main+0x80
11 00007fff`ffffe010 ffffffff`ffffffff     python3!start+0x25
12 00007fff`ffffe018 00000000`00000000     0xffffffff`ffffffff

Ezen a ponton szinte mindent meg kell tudnia tenni, amit egy távoli Windows hibakeresőhöz kapcsolódó WinDbg használatával lehet végezni egy távoli folyamatkiszolgálón keresztül. A következőket végezheti el: lépéskövetés, forrásszintű hibakeresés, töréspontok beállítása, helyi adatok vizsgálata stb.

Ha végzett a hibakereséssel, a CTRL+D billentyűkombinációval lépjen ki a gbdserver ablakból a WSL-ben.

Csatlakozás folyamatkiszolgálóhoz

Amellett, hogy egy felhasználói módú GDBServer használatával csatlakozik egy folyamathoz, beállíthat egy folyamatkiszolgálót, és listázhatja és csatolhatja a rendszer meglévő folyamatait. Ehhez a gdbserver a "--multi" parancssori argumentummal kezdődik – gdbserver --multi localhost:1234

user1@USER1:/mnt/c/Users/USER1$ sudo gdbserver --multi localhost:1234
Listening on port 1234

A folyamatkiszolgálóhoz való csatlakozáshoz válassza a "Fájl / Csatlakozás a folyamatkiszolgálóhoz" lehetőséget a WinDbg-ben, és adja meg ugyanazt a protokollsztringet, mint a fenti egyetlen folyamat gdbserver-példában:

gdb:server=localhost,port=1234

Miután az "OK" gombra kattintott, folyamatkiszolgálóként csatlakoznia kell a gdbserverhez. A dbgsrv-hez hasonlóan létrehozhat egy új folyamatot, vagy listázhatja a meglévő folyamatokat, és csatolhat egyet.

Ebben a példában használja a "Csatolás a folyamathoz" lehetőséget.

Képernyőkép a WinDbg Start hibakeresési képernyőjéről, amelyen 20 vagy több felsorolt folyamat csatolása látható.

Vegye figyelembe, hogy a Windows-folyamatokban (beleértve a PID-t, a felhasználót és a parancssort) számos hasonló dolog látható. A "csatolás a folyamathoz" párbeszédpanel egyes oszlopai nem relevánsak a Linuxhoz, és nem tartalmaznak adatokat.

A munkamenet befejezése

A CTRL+D billentyűkombinációval lépjen ki a gbdserver ablakból a WSL-ben, és válassza a Hibakeresés leállítása lehetőséget a WinDbg-ben. A munkamenet befejezéséhez bizonyos esetekben előfordulhat, hogy ki kell lépnie a hibakeresőből.

Újracsatlakozás a folyamatkiszolgálóhoz

A WinDbg felismeri a "folyamatkiszolgálót" és az "egyetlen célt" azon keresztül, hogy a gdbserver egy folyamathoz van-e csatlakoztatva. Ha valamilyen folyamathoz csatlakozik, hagyja megfagyva, zárja be a hibakeresőt, és próbáljon meg újra csatlakozni a folyamatkiszolgálóhoz, minden valószínűség szerint nem fogjuk felismerni folyamatkiszolgálóként. Ebben az esetben indítsa újra a cél gdbservert, és csatlakoztassa újra a hibakeresőt.

Linux WinDbg-funkciók

Bár a hibakereső funkcióinak nagy része a várt módon fog működni" a központi memóriaképek hibakeresésében (pl. veremjárás, szimbólumok, típusinformációk, helyi változók, szétszerelés stb.), fontos megjegyezni, hogy a teljes hibakeresési eszközlánc még nem volt tisztában az ELF, a TÖRPE és az ebből eredő különbségekkel a Windows szemantikája között. A hibakereső egyes parancsai jelenleg nem várt kimenetet eredményezhetnek. Például lm továbbra is helytelen információkat jelenít meg egy ELF-modulhoz, mivel megköveteli és manuálisan elemzi a PE-fejléceket.

Linux kernel mód EXDI-en keresztül

A Windows hibakereső támogatja a kernel hibakeresését az EXDI használatával. Ez lehetővé teszi a hardverek és operációs rendszerek széles körének hibakeresését. Az EXDI-kapcsolatok konfigurálásával és hibaelhárításával kapcsolatos általános információkért tekintse meg az EXDI Hibakereső átvitelének konfigurálását ismertető témakört.

A QEMU Kernel-Mode hibakeresés EXDI használatával történő beállításáról további információt a QEMU Kernel-Mode HIBAKERESÉS BEÁLLÍTÁSA AZ EXDI használatával című témakörben talál.

Linux szimbólumok és források

Ez a szakasz a Linux-szimbólumok alapvető használatát és rendelkezésre állását ismerteti. További információkért lásd a Linux-szimbólumokat és -forrásokat , valamint a kiterjesztett forráskód-hozzáférést.

DebugInfoD szimbólumkiszolgálók

A WinDbg 1.2104-es verziójától kezdve a forrásútvonal-parancs (.srcpath, .lsrcpath (Forráselérési út beállítása)) támogatja a DebugInfoD-kiszolgálókról a DebugInfoD* címkén keresztüli fájllekérést.

A DebugInfoD* címke egy vagy több DebugInfoD-kiszolgálóra mutathat, és mindegyik kiszolgáló URL-címe https://domain.com formátumú és * választja el őket. A kiszolgálók a forrásútvonalon felsorolt sorrendben lesznek keresve, és a fájlok az első egyező URL-címről lesznek lekérve. További információ: Source Code Extended Access.

A .sympath (Szimbólum elérési útjának beállítása) paranccsal például beállíthatja a DebugInfoD elérési útját.

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

A szimbólumok elérési útjának beállításával kapcsolatos általános információkért lásd a Szimbólumok használata című témakört.

A betöltött szimbólumokra vonatkozó információk megjelenítéséhez használja a következőt !sym noisy: . További információ: !sym.

Emellett támogatott a források automatikus letöltése a DebugInfoD-kiszolgálókról, amelyek támogatják az adott összetevőtípus visszaadását. Lényegében a következőt teheti:

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

További információ a DWARF szimbólumokkal és a Linux szimbólumkezelő segédprogramokkal, például a !sourcemap és !diesym használatáról a Linux szimbólumok és források című dokumentumban található.

C++ alkalmazás bemutatója

  1. A C++ fájl létrehozásához használjon szövegszerkesztőt (például nano vagy vi). Például:

nano DisplayGreeting.cpp

  1. A szövegszerkesztőben írja meg a C++ programot. Íme egy egyszerű program, amely üdvözléseket jelenít meg, és hibakeresésre szorul.
#include <array>
#include <cwchar>
#include <cstdio>
#include <iostream>
using namespace std;

void GetCppConGreeting(wchar_t* buffer, size_t size)
{
    wchar_t const* const message = L"HELLO FROM THE WINDBG TEAM. GOOD LUCK IN ALL OF YOUR TIME TRAVEL DEBUGGING!";
    wcsncpy(buffer, message, size);
}

int main()
{
    std::array<wchar_t, 50> greeting{};
    GetCppConGreeting(greeting.data(), greeting.size());

    cin.get();
    wprintf(L"%ls\n", greeting.data());

    return 0;
}
  1. Mentse (CTRL-O) és lépjen ki (CTRL-X) a nanoszerkesztőből.

  2. Állítsa össze a C++ fájlt a g++-tal. A -o beállítás a kimeneti fájl nevének megadására szolgál, a -g beállítás pedig egy szimbólumfájlt hoz létre:

g++ DisplayGreeting.cpp -g -o DisplayGreeting

  1. Ha a kódban nincsenek hibák, a g++ parancs létrehoz egy DisplayGreeting nevű végrehajtható fájlt a címtárban.

  2. A programot a következő paranccsal futtathatja:

./DisplayGreeting

  1. A visszatérési kulcs lenyomásával megjelenik az üzenet az alkalmazásban. A kimenetet tekintve úgy tűnik, hogy a megszólítás csonkolt, és helyette a "????" jelenik meg.

HELLO FROM THE WINDBG TEAM. GOOD LUCK IN ALL OF YO????

A DisplayGreeting hibakeresése

  1. Ha a kód készen áll a futtatásra, elindíthatjuk az alkalmazást a gdbserver használatával.

gdbserver localhost:1234 DisplayGreeting

  1. Nyissa meg a WinDbg fájlt, és válassza a "Fájl / Csatlakozás távoli hibakeresőhöz" lehetőséget, és adjon meg egy protokollsztringet a kapcsolathoz. Ebben a példában a következőt fogjuk használni: gdb:server=localhost,port=1234.

  2. A csatlakozás után a kimenetnek azt kell jeleznie, hogy az 1234-ös porton figyel, és hogy létrejön a távoli hibakeresési kapcsolat.

Bob@Bob6:/mnt/c/Users/bob$ gdbserver localhost:1234 DisplayGreeting
Process /mnt/c/Users/bob/DisplayGreeting created; pid = 725
Listening on port 1234
Remote debugging from host 127.0.0.1, port 47700

Ahogy korábban említettük, egyes Linux-környezetek esetében előfordulhat, hogy a parancsot rendszergazdaként kell futtatni, általában sudo használatával. Körültekintően engedélyezze a hibakereső rendszergazda legfelső szintű hozzáférését, és csak akkor használja ezt, ha szükséges.

Forrás- és szimbólumútvonalak hozzáadása a hibakereső munkamenethez

Töréspontok beállításához és a forráskód és a változók megtekintéséhez állítsa be a szimbólumokat és a forrás elérési útját. A szimbólumok elérési útjának beállításával kapcsolatos általános információkért lásd a Szimbólumok használata című témakört.

A szimbólum elérési útjának a hibakereső munkamenethez való hozzáadásához használható .sympath . Ebben a példában a kód ezen a helyen fut a WSL Linux Ubuntu-ban egy Bob nevű felhasználó számára.

\\wsl$\Ubuntu\mnt\c\Users\Bob\

A WSL-ben ez a könyvtár a következő Windows operációs rendszer helyére van leképezve: C:\Users\Bob\

Tehát ezt a két parancsot használják.

.sympath C:\Users\Bob\

.srcpath C:\Users\Bob\

A WSL fájlrendszerről további információt a WSL fájlengedélyei című témakörben talál.

  1. Ha további Linux operációs rendszer szimbólumokat szeretne használni, adja hozzá a DebugInfoD szimbólumokat az .sympath útvonallal, mint például itt.

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

  1. Emellett támogatott a források automatikus letöltése a DebugInfoD-kiszolgálókról, amelyek támogatják az adott összetevőtípus visszaadását. Ennek kihasználásához adja hozzá a elfutils kiszolgálót a .srcpath használatával.

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

Töréspont beállítása

Állítson be egy töréspontot a DisplayGreeting alkalmazás fő részén.

0:000> bp DisplayGreeting!main
0:000> bl
     0 e Disable Clear  00005555`55555225  [/mnt/c/Users/bob/DisplayGreeting.cpp @ 14]     0001 (0001)  0:**** DisplayGreeting!main

A Kódvégrehajtás újraindításához használja a Go parancsot vagy a menüt.

Forráskód betöltése

A szimbólumok újratöltéséhez használja az .reload parancsot.

lm A paranccsal győződjön meg arról, hogy a DisplayGreeting alkalmazást futtatjuk.

0:000> lm
start             end                 module name
00005555`55554000 00005555`55558140   DisplayGreeting T (service symbols: DWARF Private Symbols)        c:\users\bob\DisplayGreeting
00007fff`f7a54000 00007fff`f7a732e8   libgcc_s_so   (deferred)             
00007fff`f7a74000 00007fff`f7b5a108   libm_so    (deferred)             
00007fff`f7b5b000 00007fff`f7d82e50   libc_so  T (service symbols: DWARF Private Symbols)        C:\ProgramData\Dbg\sym\_.debug\elf-buildid-sym-a43bfc8428df6623cd498c9c0caeb91aec9be4f9\_.debug
00007fff`f7d83000 00007fff`f7fae8c0   libstdc___so   (deferred)             
00007fff`f7fc1000 00007fff`f7fc1000   linux_vdso_so   (deferred)             
00007fff`f7fc3000 00007fff`f7ffe2d8   ld_linux_x86_64_so T (service symbols: DWARF Private Symbols)        C:\ProgramData\Dbg\sym\_.debug\elf-buildid-sym-9718d3757f00d2366056830aae09698dbd35e32c\_.debug

Ha a parancs hozzáférést aktivál a megjelenítendő üdvözlőkódhoz, az megjelenik a WinDbg-ben.

képernyőkép a DisplayGreeting.cpp kódról a WinDbg-ben, ahol a töréspont a 19. sorban, wprint-nél van beállítva

A verem listázásához használd a "k" parancsot.

0:000> k
 # Child-SP          RetAddr               Call Site
00 00007fff`ffffde00 00007fff`f7b84d90     DisplayGreeting!main+0x1f [/mnt/c/Users/BOB/DisplayGreeting.cpp @ 15] 
01 00007fff`ffffdef0 00007fff`f7b84e40     libc_so!__libc_start_call_main+0x80 [./csu/../sysdeps/x86/libc-start.c @ 58] 
02 00007fff`ffffdf90 00005555`55555125     libc_so!__libc_start_main_impl+0x80 [./csu/../sysdeps/nptl/libc_start_call_main.h @ 379] 
03 00007fff`ffffdfe0 ffffffff`ffffffff     DisplayGreeting!start+0x25
04 00007fff`ffffdfe8 00000000`00000000     0xffffffff`ffffffff```

A helyi változó üdvözlésének megtekintéséhez használja a dx parancsot. Ne feledje, hogy mérete 50.

0:000> dx greeting
greeting                 : { size=50 } [Type: std::array<wchar_t, 50>]
    [<Raw View>]     [Type: std::array<wchar_t, 50>]

Nézze át a kódot, és vegye figyelembe, hogy az 50 nem feltétlenül megfelelő méretű az üdvözlő üzenethez.

wchar_t const* const message = L"HELLO FROM THE WINDBG TEAM. GOOD LUCK IN ALL OF YOUR TIME TRAVEL

Ezt a megszólítás helyi változójának kibontásával és a üdvözlés csonkolásának megtekintésével erősítse meg.

A gdbserver-kapcsolat hibaelhárítása

--debug A beállítással további információkat jeleníthet meg a gdbserver konzolon a kapcsolat állapotával kapcsolatos további információk gyűjtéséhez. Például egy folyamatkiszolgáló elindításához használja ezt a parancsot.

gdbserver --debug --multi localhost:1234

Lásd még

Linux-szimbólumok és -források

Kiterjesztett hozzáférés a forráskódhoz

Linux-összeomlási memóriaképek

ELFUTILS debuginfod

A legjobb távoli hibakeresési módszer kiválasztása