Aracılığıyla paylaş


Linux canlı uzaktan işlem hata ayıklama

Bu makalede, Linux'a canlı windbg bağlantısının nasıl kuruldığı açıklanır. Linux'ta canlı uzaktan işlem hata ayıklaması için WinDbg sürüm 1.2402.24001.0 veya üzeri gerekir.

GNU Hata Ayıklayıcısı - GDBServer, WinDbg bağlantısını desteklemek için Linux üzerinde kullanılır. GDBServer hakkında daha fazla bilgi için bkz https://en.wikipedia.org/wiki/Gdbserver. . Uzak gdb hata ayıklama belgelerini görüntülemek için burada bir yer vardır - https://sourceware.org/gdb/current/onlinedocs/gdb#Remote-Debugging

Buradaki örneklerde Linux için Windows Alt Sistemi (WSL) kullanılmaktadır ancak diğer Linux uygulamaları da kullanılabilir.

WinDbg uzak işlem hata ayıklama türleri

WinDbg ile uzaktan hata ayıklama gerçekleştirmenin iki birincil yöntemi vardır: İşlem sunucusu veya KD bağlantı sunucusu. İşlem sunucuları kullanıcı modu hata ayıklaması için kullanılır; KD bağlantı sunucuları çekirdek modu hata ayıklaması için kullanılır. Bu WinDbg bağlantı türleri hakkında genel bilgi için bkz. İşlem Sunucuları (Kullanıcı Modu) ve KD Bağlantı Sunucuları (Çekirdek Modu ).

Linux kullanıcı modu işlemlerinde hata ayıklamaya başlamanın iki yolu vardır. Gdbserver'ı belirli bir işlemde başlatabilir veya gdbserver'ı mevcut işlemleri listeleyip ekleyebileceğiniz bir işlem sunucusu olarak başlatabilirsiniz. Bu, Windows'ta DbgSrv (dbgsrv.exe) işlem sunucusuna çok benzer. Daha fazla bilgi için bkz . İşlem Sunucusunu Etkinleştirme.

Kullanıcı modunda Linux işlem hata ayıklama

Belirli bir tek kullanıcı modu işlemine veya çok modlu bir işleme bağlanarak tüm işlemi bir listede görmek ve bağlanmak için birini seçmek mümkündür. Her iki yöntem de bu konuda açıklanmıştır. Her iki yöntem de, daha sonra açıklanan aynı bağlantı dizesi söz dizimini paylaşır.

gdbserver bağlantı dizesi biçimi

gdbserver'a bağlanmak için kullanılan biçim "protocol:arguments" biçimindedir; burada bağımsız değişkenler virgülle ayrılmış bir "argument=value" listesidir. Kullanıcı modu gdbserver bağlantısı için protokol gdb ve bağımsız değişken kümesi aşağıdaki gibidir.

server=<address> - Zorunlu: Bağlanacak gdbserver'ın IP adresini gösterir.

port=<port> - Zorunlu: Bağlanacak gdbserver'ın bağlantı noktası numarasını gösterir.

threadEvents=<true|false> - İsteğe bağlı: gdbserver'ın bu sürümü için iş parçacığı olaylarının durdurma modunda düzgün çalışıp çalışmadığını gösterir.

Geçerli gdbserver sürümlerinde, durdurma modundaki bir gdbserver ile iş parçacığı olaylarını etkinleştirme işlemi (WinDbg'nin kullandığı) gdbserver'ın çökmesine neden olacak bir problem vardır. Bu değer false ise (varsayılan değer), iş parçacığı başlatma ve durdurma olayları sentezlenir, ancak iş parçacığı oluşturma/yok etme zamanından önemli ölçüde daha geç görünebilir. Bunun için bir düzeltme gdbserver'da kullanılabilir olduğunda, gerçek olaylar bu seçenek aracılığıyla etkinleştirilebilir.

Tek Kullanıcı Modu İşlemine Bağlanma

Bu bölümde, WinDbg kullanarak Linux'ta tek bir kullanıcı modu işlemini tanımlama ve bunlara bağlanma açıklanmaktadır.

WSL (Linux için Windows Alt Sistemi)

Buradaki örneklerde WSL (Linux için Windows Alt Sistemi) kullanılır, ancak diğer Linux uygulamaları kullanılabilir. WSL'yi ayarlama ve kullanma hakkında bilgi için bkz:

İstenen işlemi seçin

Bağlanacak çalışan işlemi belirlemek için komutunu kullanarak ps -A Linux'taki işlemleri listeleyin.

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

Bu örnek kılavuzda python3'e bağlanacağız.

Hedef sistem IP adresini bulma

Uzak bir Linux hedefine bağlanıyorsanız, dış IP adresini belirlemek için gibi ip route showbir komut kullanın.

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

Bu kılavuzda, aynı bilgisayarda çalışan WSL'ye bağlanacak ve localhost'un IP adresini kullanacağız.

Seçili işleme GDBServer ekleme

WSL Linux konsolunda gdbserver localhost:1234 python3 yazarak gdbserver'ı 1234 numaralı portta başlatın ve python3 işlemine bağlayın.

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

Bazı Linux ortamlarında komutun yönetici olarak çalıştırılması gerekebilir, örneğin sudo - sudo gdbserver localhost:1234 python3kullanılır. Hata ayıklayıcısı yönetici kök düzeyi erişimini etkinleştirirken dikkatli olun ve bunu yalnızca gerekli olduğunda kullanın.

WinDbg'de işlem sunucusu bağlantısı oluşturma

WinDbg'yi açın ve "Dosya / Uzak Hata Ayıklayıcıya Bağlan" seçeneğini belirleyin ve bağlantı için bir protokol dizesi girin. Bu örnekte şunu kullanacağız: gdb:server=localhost,port=1234.

Bağlantı dizesini gösteren WinDbg Hata ayıklamayı başlat ekranının ekran görüntüsü.

Tamam düğmesine tıkladığınızda, hata ayıklayıcı gdb sunucusuna bağlanmalı ve ilk işlem başlangıç sonunda olmanız gerekir.

İlk kesme noktasına geçtikten sonra 'g' tuşuna birkaç kez basabilirsiniz. Modül yükleme iletileri alırsınız ve sxe stilinde "modül yükünde kesme" etkinlikleri düzgün çalışmalıdır.

Hata ayıklama simgeleri önbelleğe yüklendiğinden, bu noktaya ulaşmak biraz zaman alabilir. Sembol sunucusu veya yerel arama yolunuz aracılığıyla sembolleri ve ikili dosyaları aramaya ek olarak, GDBServer tümleştirmesi symsrv veya yerel olarak bulunamazsa bu dosyaları uzak dosya sisteminden çekme özelliğine sahiptir. Bu genellikle symsrv'den veya yerel bir arama yolundan sembol almaktan çok daha yavaş bir işlemdir, ancak uygun simgeleri bularak genel deneyimi daha iyi bir deneyim haline getirir.

Yığını listelemek için k stacks komutunu kullanın. Python3 modüllerini gösterdiği için WinDbg kullanarak Linux'ta python3 hata ayıklaması yaptığımız doğrulanır.

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

Bu noktada, uzak işlem sunucusu üzerinden uzak bir Windows hata ayıklayıcısına bağlı WinDbg kullanılarak yapılabilecek neredeyse her şeyi yapabilmeniz gerekir. Adım atabilir, kaynak düzeyinde hata ayıklayabilir, kesme noktaları ayarlayabilir, yerel ayarları inceleyebilirsiniz.

Hata ayıklamayı tamamladıktan sonra WSL'de gbdserver penceresinden çıkmak için CTRL+D tuşlarını kullanın.

İşlem Sunucusuna Bağlanma

Kullanıcı modu GDBServer aracılığıyla tek bir sürece bağlanmaya ek olarak, bir işlem sunucusu olarak GDBServer'ı ayarlayabilir ve sistemdeki mevcut süreçleri listeleyip bunlara bağlanabilirsiniz. Bunu yapmak için gdbserver "--multi" komut satırı bağımsız değişkeniyle başlatılır - gdbserver --multi localhost:1234

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

İşlem sunucusuna bağlanmak için WinDbg'de "Dosya / İşlem sunucusuna bağlan" seçeneğini belirleyin ve yukarıdaki tek işlem gdbserver örneğinde yaptığınız protokol dizesini girin:

gdb:server=localhost,port=1234

"Tamam" düğmesine tıkladığınızda gdbserver'a işlem sunucusu olarak bağlanmalısınız. dbgsrv'de olduğu gibi, yeni bir işlem oluşturabilir veya mevcut işlemleri listeleyip bir işleme ekleyebilirsiniz.

Bu örnekte, "İşleme bağlan" seçeneğini kullanın.

WinDbg Hata ayıklamayı başlat ekranının ekran görüntüsü, 20 ve daha fazla listelenen işlemle işleme eklenmesini gösterir.

Windows işlemleri (PID, kullanıcı ve komut satırı dahil) için görünür olan birçok öğeyi göreceğinizi unutmayın. "İşleme ekle" iletişim kutusundaki sütunlardan bazıları Linux ile ilgili değildir ve veri içermez.

Oturumu sonlandırma

WSL'de gbdserver penceresinden çıkmak için CTRL+D tuşlarını kullanın ve WinDbg'de hata ayıklamayı durdur'u seçin. Oturumu sonlandırmak için bazı durumlarda hata ayıklayıcıdan çıkmanız gerekebilir.

İşlem sunucusuna yeniden bağlanma

WinDbg, gdbserver'ın bir işleme bağlı olup olmadığına göre "işlem sunucusu" ile "tek hedef"i ayırt eder. Bir işleme bağlanıp, onu donmuş halde bırakır, hata ayıklayıcısını kapatır ve işlem sunucusuna yeniden bağlanmayı denerseniz, büyük ihtimalle bunu bir işlem sunucusu olarak tanıyamayız. Bu durumda hedef gdbserver'ı yeniden başlatın ve hata ayıklayıcıyı yeniden bağlayın.

Linux WinDbg işlevselliği

Hata ayıklayıcının işlevselliğinin çoğu beklendiği gibi çekirdek dökümlerini ayıklamada (örn. yığın yürütme, semboller, tür bilgileri, yerel değişkenler, ayrıştırma vb.) çalışacaktır, ancak hata ayıklama araç zincirinin tamamının ELF, DWARF ve Windows semantiklerinden kaynaklanan farklardan henüz haberdar edilmediğini unutmayın. Hata ayıklayıcıdaki bazı komutlar şu anda beklenmeyen çıkışa neden olabilir. Örneğin, lm bir ELF modülü için beklediğiniz gibi yanlış bilgiler görüntülemeye ve PE üst bilgilerini el ile ayrıştırmaya devam eder.

EXDI aracılığıyla Linux Çekirdek Modu

Windows hata ayıklayıcısı, EXDI kullanarak çekirdek hata ayıklamasını destekler. Bu, çok çeşitli donanım ve işletim sistemlerinde hata ayıklamaya olanak tanır. EXDI bağlantılarını yapılandırma ve sorunlarını giderme hakkında genel bilgi için bkz. EXDI Hata Ayıklayıcı Aktarımını Yapılandırma.

EXDI kullanarak QEMU Kernel-Mode Hata Ayıklamayı ayarlama hakkında bilgi için bkz. EXDI Kullanarak QEMU Kernel-Mode Hata Ayıklamayı Ayarlama.

Linux Sembolleri ve Kaynakları

Bu bölümde Linux sembollerinin temel kullanımı ve kullanılabilirliği açıklanmaktadır. Daha ayrıntılı bilgi için bkz . Linux sembolleri ve kaynakları veKaynak Kodu Genişletilmiş Erişimi.

DebugInfoD sembol sunucuları

WinDbg sürüm 1.2104'ten başlayarak, kaynak yol komutu (.srcpath, .lsrcpath (Kaynak Yolunu Ayarla)) DebugInfoD sunucularından etiket aracılığıyla DebugInfoD* dosya almayı destekler.

DebugInfoD* etiketi, her bir sunucu URL'si https://domain.com biçiminde biçimlendirilmiş ve * ile ayrılmış olarak bir veya daha fazla DebugInfoD sunucusuna işaret edebilir. Sunucular, kaynak yolda listelenen sırayla aranacak ve dosyalar eşleşen ilk URL'den alınacaktır. Daha fazla bilgi için bkz. Kaynak Kodu Genişletilmiş Erişim.

Örneğin, . sympath (Sembol Yolunu Ayarla) komutunu kullanarak bunun gibi bir DebugInfoD yolu ayarlayabilirsiniz.

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

Sembol yolunu ayarlama hakkında genel bilgi için bkz. Sembolleri Kullanma.

Yüklenen simgelerle ilgili bilgileri görüntülemek için kullanın !sym noisy. Daha fazla bilgi için bkz. !sym.

Ayrıca, bu yapıt türünü döndürmeyi destekleyen DebugInfoD sunucularından kaynakların otomatik olarak indirilmesi de desteklenir. Özünde şunları yapabilirsiniz:

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

DWARF sembolleri ve !sourcemap, !diesym gibi Linux simge yardımcı programları ile çalışma hakkında daha fazla bilgi için bkz. Linux sembolleri ve kaynakları.

C++ uygulama kılavuzu

  1. C++ dosyanızı oluşturmak için bir metin düzenleyicisi (nano veya vi gibi) kullanın. Örneğin:

nano DisplayGreeting.cpp

  1. Metin düzenleyicisinde C++ programınızı yazın. Hata ayıklaması gereken selamlamaları görüntüleyen basit bir program aşağıdadır:
#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. (CTRL-O) kaydedin ve nano düzenleyiciden (CTRL-X) çıkın.

  2. C++ dosyasını g++ kullanarak derleyin. -o seçeneği çıkış dosyası adını belirtmek için kullanılır ve -g seçeneği bir sembol dosyası oluşturur:

g++ DisplayGreeting.cpp -g -o DisplayGreeting

  1. Kodunuzda hata yoksa g++ komutu dizininizde DisplayGreeting adlı bir yürütülebilir dosya oluşturur.

  2. Aşağıdaki komutu kullanarak programı çalıştırabilirsiniz:

./DisplayGreeting

  1. Dönüş tuşuna basıldığında ileti uygulamada görüntülenir. Çıktıya baktığımızda, selamın kesildiği ve bunun yerine "????" görüntülendiği görülüyor.

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

DisplayGreeting Hatalarını Ayıklama

  1. Kod çalışmaya hazır olduktan sonra gdbserver kullanarak uygulamayı başlatabiliriz.

gdbserver localhost:1234 DisplayGreeting

  1. WinDbg'yi açın ve "Dosya / Uzak Hata Ayıklayıcıya Bağlan" seçeneğini belirleyin ve bağlantı için bir protokol dizesi girin. Bu örnekte şunu kullanacağız: gdb:server=localhost,port=1234.

  2. Bağlandıktan sonra çıkış, 1234 numaralı bağlantı noktasında dinlediğini ve uzaktan hata ayıklama bağlantısının kurulduğunu göstermelidir.

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

Daha önce belirtildiği gibi, bazı Linux ortamlarında komutun genellikle sudo kullanılarak yönetici olarak çalıştırılması gerekebilir. Hata ayıklayıcısı yönetici kök düzeyi erişimini etkinleştirirken dikkatli olun ve bunu yalnızca gerekli olduğunda kullanın.

Kaynak ve simge yollarını hata ayıklayıcı oturumuna ekleme

Kesme noktalarını ayarlamak ve kaynak kodu ve değişkenleri görüntülemek için simgeleri ve kaynak yolunu ayarlayın. Sembol yolunu ayarlama hakkında genel bilgi için bkz. Sembolleri Kullanma.

Hata ayıklayıcı oturumuna sembol yolunu eklemek için kullanın .sympath . Bu örnekte kod, Bob adlı bir kullanıcı için WSL Linux Ubuntu'daki bu konumda çalışıyor.

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

WSL'de bu dizin şu Windows işletim sistemi konumuna eşler: C:\Users\Bob\

Bu nedenle bu iki komut kullanılır.

.sympath C:\Users\Bob\

.srcpath C:\Users\Bob\

WSL dosya sistemi hakkında daha fazla bilgi için bkz. WSL için Dosya İzinleri.

  1. Ek Linux işletim sistemi simgelerinden yararlanmak için,.sympath konumunu kullanarak DebugInfoD simgelerini ekleyin.

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

  1. Ayrıca, bu yapıt türünü döndürmeyi destekleyen DebugInfoD sunucularından kaynakların otomatik olarak indirilmesi de desteklenir. Bundan yararlanmak için .srcpath kullanarak elfutils sunucusunu ekleyin.

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

Kesme noktası ayarlama

DisplayGreeting uygulamasının ana bölümünde bir kesme noktası ayarlayı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

Kod yürütmeyi yeniden başlatmak için Git komutunu veya menü seçeneğini kullanın.

Kaynak kodu yükleme

Sembolleri yeniden yüklemek için .reload komutunu kullanın.

lm DisplayGreeting uygulamasını çalıştırdığınızı onaylamak için komutunu kullanın.

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

Komut görüntüleme selamlama koduna erişimi tetikledikten sonra WinDbg'de görüntülenir.

WinDbg'de 19. satırda kesme noktası ayarlanmış DisplayGreeting.cpp kodun ekran görüntüsü, wprint

Yığını listelemek için 'k' komutunu kullanın.

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```

Yerel değişken karşılamasını görüntülemek için dx komutunu kullanın. Boyutunun 50 olduğunu unutmayın.

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

Koda bakın ve 50'nin selamlama iletisi için yeterli boyutta olmayabileceğini unutmayın.

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

Selamlama için locals değişkenini genişleterek ve selamlamanın kesildiğini görerek bunu onaylayın.

gdbserver bağlantısı sorunlarını giderme

--debug Bağlantı durumu hakkında daha fazla bilgi toplamak için gdbserver konsolunda ek bilgi görüntülemek için seçeneğini kullanın. Örneğin, bir işlem sunucusu başlatmak için bu komutu kullanın.

gdbserver --debug --multi localhost:1234

Ayrıca bakınız

Linux sembolleri ve kaynakları

Kaynak Kodu Genişletilmiş Erişimi

Linux çökme dökümleri

ELFUTILS debuginfod

En İyi Uzaktan Hata Ayıklama Yöntemini Seçme