Penelusuran kesalahan proses jarak jauh langsung Linux
Artikel ini menjelaskan cara membuat koneksi WinDbg langsung ke Linux. Penelusuran kesalahan proses jarak jauh langsung di Linux memerlukan WinDbg versi 1.2402.24001.0 atau lebih tinggi.
Debugger GNU - GDBServer, digunakan di Linux untuk mendukung koneksi WinDbg. Untuk informasi selengkapnya tentang GDBServer, lihat https://en.wikipedia.org/wiki/Gdbserver. Satu tempat untuk melihat dokumentasi untuk penelusuran kesalahan gdb jarak jauh ada di sini - https://sourceware.org/gdb/current/onlinedocs/gdb#Remote-Debugging
Contoh di sini menggunakan Subsistem Windows untuk Linux (WSL), tetapi implementasi Linux lainnya juga dapat digunakan.
Jenis WinDbg dari penelusuran kesalahan proses jarak jauh
Ada dua metode utama untuk melakukan penelusuran kesalahan jarak jauh dengan WinDbg - Server proses atau server koneksi KD. Server proses digunakan untuk penelusuran kesalahan mode pengguna; Server koneksi KD digunakan untuk penelusuran kesalahan mode kernel. Lihat Server Proses (Mode Pengguna) dan Server Koneksi KD (Mode Kernel) untuk informasi umum tentang jenis koneksi WinDbg ini.
Ada dua cara untuk mulai men-debug proses mode pengguna Linux. Anda dapat memulai gdbserver pada proses tertentu atau Anda dapat memulai gdbserver sebagai server proses yang dapat mencantumkan dan melampirkan ke proses yang ada. Ini mirip seperti server proses DbgSrv (dbgsrv.exe) di Windows. Untuk informasi selengkapnya, lihat Mengaktifkan Server Proses.
Debugging proses Linux mode pengguna
Dimungkinkan untuk terhubung ke proses mode pengguna tunggal tertentu, atau dalam multi-mode, untuk melihat semua proses dalam daftar dan memilih salah satu untuk disambungkan. Kedua metode dijelaskan dalam topik ini. Kedua metode berbagi sintaks string koneksi yang sama, dijelaskan berikutnya.
Format untuk string koneksi gdbserver
Format yang digunakan untuk menyambungkan ke gdbserver adalah "protocol:arguments" di mana argumen adalah daftar "argument=value" yang dipisahkan koma. Untuk koneksi gdbserver mode pengguna, protokolnya adalah gdb dan kumpulan argumen adalah sebagai berikut.
server=<address>
- Wajib: menunjukkan alamat IP gdbserver untuk disambungkan.
port=<port>
- Wajib: menunjukkan nomor port gdbserver untuk disambungkan.
threadEvents=<true|false>
- Opsional: menunjukkan apakah peristiwa utas untuk versi gdbserver ini berfungsi dengan benar dalam mode berhenti.
Ada masalah dalam rilis gdbserver saat ini, di mana mengaktifkan peristiwa utas dengan server dalam mode berhenti (yang digunakan WinDbg) akan menyebabkan gdbserver mengalami crash. Jika nilai ini salah (nilai default), peristiwa mulai dan hentikan utas akan disintesis tetapi dapat muncul secara signifikan lebih lambat dari waktu aktual pembuatan/penghancuran utas. Ketika perbaikan untuk ini tersedia di gdbserver, peristiwa aktual dapat diaktifkan melalui opsi ini.
Menyambungkan ke Proses Mode Pengguna Tunggal
Bagian ini menjelaskan cara mengidentifikasi dan menyambungkan ke proses mode pengguna tunggal di Linux, menggunakan WinDbg.
WSL (Subsistem Windows untuk Linux)
Contoh di sini menggunakan WSL (Subsistem Windows untuk Linux), tetapi implementasi Linux lainnya dapat digunakan. Untuk informasi tentang menyiapkan dan menggunakan WSL, lihat:
- Cara menginstal Linux di Windows dengan WSL
- Menyiapkan lingkungan pengembangan WSL
- Mengakses aplikasi jaringan dengan WSL
- Pengaturan Intune untuk WSL
Pilih proses yang diinginkan
Mencantumkan proses di Linux menggunakan ps -A
perintah untuk menentukan proses yang sedang berjalan untuk disambungkan.
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
Dalam contoh panduan ini, kita akan terhubung ke python3.
Menemukan alamat IP sistem target
Jika menyambungkan ke target linux jarak jauh, gunakan perintah seperti ip route show
untuk menentukan alamat IP eksternal.
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
Dalam panduan ini, kami akan terhubung ke WSL yang berjalan pada PC yang sama, dan akan menggunakan alamat IP localhost.
Lampirkan GDBServer ke proses yang dipilih
Pada konsol linux WSL, masukkan gdbserver localhost:1234 python3
untuk memulai gdbserver pada port 1234, dan lampirkan ke proses python3.
USER1@USER1:/mnt/c/Users/USER1$ gdbserver localhost:1234 python3
Process python3 created; pid = 1211
Listening on port 1234
Untuk beberapa lingkungan linux, perintah mungkin perlu dijalankan sebagai administrator, misalnya menggunakan sudo - sudo gdbserver localhost:1234 python3
. Berhati-hatilah dengan mengaktifkan akses tingkat root administrator debugger dan hanya gunakan ini saat diperlukan.
Membuat koneksi server proses di WinDbg
Buka WinDbg, dan pilih "File / Sambungkan ke Debugger Jarak Jauh" dan masukkan string protokol untuk koneksi. Untuk contoh ini, kita akan menggunakan: gdb:server=localhost,port=1234
.
Setelah Anda mengklik tombol OK, debugger harus terhubung ke gdbserver dan Anda harus berada di hentian mulai proses awal.
Setelah Anda berada di titik henti awal, Anda dapat menekan 'g' beberapa kali. Anda akan mendapatkan pesan beban modul (dan gaya sxe "break on module load" peristiwa harus berfungsi dengan baik).
Perhatikan bahwa mungkin perlu waktu sejenak untuk sampai ke titik itu, karena simbol debug dimuat ke dalam cache. Selain mencari simbol dan biner melalui server simbol atau jalur pencarian lokal Anda, integrasi GDBServer memiliki kemampuan menarik file-file ini dari sistem file jarak jauh jika tidak dapat ditemukan melalui symsrv atau secara lokal. Ini biasanya merupakan operasi yang jauh lebih lambat daripada mendapatkan simbol dari symsrv atau jalur pencarian lokal tetapi membuat pengalaman keseluruhan menjadi lebih baik dengan menemukan simbol yang sesuai.
Gunakan perintah tumpukan k untuk mencantumkan tumpukan. Ini menunjukkan modul python3, jadi ini mengonfirmasi bahwa kami men-debug python3 di Linux menggunakan WinDbg.
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
Pada titik ini, Anda harus dapat melakukan hampir semua yang dapat dilakukan menggunakan WinDbg yang terpasang pada debugger Windows jarak jauh melalui server proses jarak jauh. Anda dapat melangkah, debug tingkat sumber, mengatur titik henti, memeriksa lokal, dll..
Setelah Anda selesai men-debug, gunakan CTRL+D untuk keluar dari jendela gbdserver di WSL.
Menyambungkan ke Server Proses
Selain menyambungkan ke satu proses melalui mode pengguna GDBServer, Anda dapat menyiapkannya sebagai server proses dan mencantumkan dan melampirkan ke proses yang ada pada sistem. Untuk melakukan ini, gdbserver dimulai dengan argumen baris perintah "--multi" - gdbserver --multi localhost:1234
user1@USER1:/mnt/c/Users/USER1$ sudo gdbserver --multi localhost:1234
Listening on port 1234
Untuk menyambungkan ke server proses, pilih "File / Sambungkan ke server proses" di WinDbg dan masukkan string protokol yang sama seperti yang Anda lakukan dengan contoh gdbserver proses tunggal di atas:
gdb:server=localhost,port=1234
Setelah Anda mengklik tombol "OK", Anda harus terhubung ke gdbserver sebagai server proses. Seperti halnya dbgsrv, Anda dapat menelurkan proses baru atau Anda dapat mencantumkan proses yang ada dan melampirkan ke proses tersebut.
Dalam contoh ini, gunakan opsi "Lampirkan ke proses".
Perhatikan bahwa Anda akan melihat banyak hal yang sama yang terlihat untuk proses Windows (termasuk PID, pengguna, dan baris perintah). Beberapa kolom dalam dialog "lampirkan ke proses" tidak relevan dengan Linux dan tidak akan berisi data.
Mengakhiri sesi
Gunakan CTRL+D untuk keluar dari jendela gbdserver di WSL dan pilih hentikan penelusuran kesalahan di WinDbg. Untuk mengakhiri sesi, dalam beberapa kasus Anda mungkin perlu keluar dari debugger.
Menyambungkan kembali ke server proses
WinDbg mengenali "server proses" versus "target tunggal" melalui apakah gdbserver dilampirkan ke proses atau tidak. Jika Anda melampirkan ke beberapa proses, biarkan dibekukan, tutup debugger, dan coba sambungkan kembali ke server proses, dalam semua kemungkinan, kami tidak akan mengenalinya sebagai server proses. Dalam situasi ini, mulai ulang target gdbserver dan sambungkan kembali debugger.
Fungsionalitas Linux WinDbg
Meskipun sebagian besar fungsionalitas debugger akan berfungsi seperti yang diharapkan" dalam debugging core dump (misalnya: stack walking, simbol, informasi jenis, variabel lokal, pembongkaran, dll...), penting untuk dicatat bahwa seluruh toolchain debugging belum mengetahui ELF, DWARF, dan perbedaan yang dihasilkan dari semantik Windows. Beberapa perintah dalam debugger saat ini dapat mengakibatkan output yang tidak terduga. Misalnya, lm
masih akan menampilkan informasi yang salah untuk modul ELF seperti yang diharapkan dan mengurai header PE secara manual.
Mode Kernel Linux melalui EXDI
Debugger Windows mendukung penelusuran kesalahan kernel menggunakan EXDI. Ini memungkinkan penelusuran kesalahan berbagai perangkat keras dan sistem operasi. Untuk informasi umum tentang menyiapkan konfigurasi dan pemecahan masalah koneksi EXDI, lihat Mengonfigurasi Exdi Debugger Transport.
Untuk informasi tentang cara menyiapkan Debugging Mode Kernel QEMU menggunakan EXDI, lihat Menyiapkan Debugging Mode Kernel QEMU Menggunakan EXDI.
Simbol dan Sumber Linux
Bagian ini menjelaskan penggunaan dasar dan ketersediaan simbol Linux. Untuk informasi selengkapnya, lihat Simbol dan sumber Linux serta Akses Yang Diperluas Kode Sumber.
Server simbol DebugInfoD
Memulai WinDbg versi 1.2104, perintah jalur sumber (.srcpath, .lsrcpath (Set Source Path)) mendukung pengambilan file dari server DebugInfoD melalui DebugInfoD*
tag.
Tag DebugInfoD*
dapat menunjuk ke satu atau beberapa server DebugInfoD dengan setiap URL server diformat sebagai https://domain.com
dan dipisahkan oleh *
. Server akan dicari dalam urutan yang sama seperti yang tercantum di jalur sumber dan file akan diambil dari URL pertama yang cocok. Untuk informasi selengkapnya, lihat Kode Sumber Akses yang Diperluas.
Misalnya Anda dapat menggunakan perintah .sympath (Atur Jalur Simbol) untuk mengatur jalur DebugInfoD seperti ini.
.sympath+ DebugInfoD*https://debuginfod.elfutils.org
Untuk informasi umum tentang mengatur jalur simbol, lihat Menggunakan Simbol.
Untuk menampilkan informasi tentang simbol yang sedang dimuat, gunakan !sym noisy
. Untuk informasi selengkapnya, lihat !sym.
Juga didukung adalah pengunduhan otomatis sumber dari server DebugInfoD yang mendukung pengembalian jenis artefak tersebut. Anda dapat, pada dasarnya melakukan:
.srcpath+ DebugInfoD*https://debuginfod.elfutils.org
Untuk informasi selengkapnya tentang bekerja dengan simbol DWARF dan utilitas simbol Linux, seperti !sourcemap
dan , lihat simbol dan sumber!diesym
Linux.
Panduan aplikasi C++
- Gunakan editor teks (seperti nano atau vi) untuk membuat file C++Anda. Contohnya:
nano DisplayGreeting.cpp
- Di editor teks, tulis program C++ Anda. Berikut adalah program sederhana yang menampilkan salam, yang perlu di-debug:
#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;
}
Simpan (CTRL-O) dan keluar (CTRL-X) editor nano.
Kompilasi file C++ menggunakan g++. Opsi -o digunakan untuk menentukan nama file output, dan opsi -g menghasilkan file simbol:
g++ DisplayGreeting.cpp -g -o DisplayGreeting
Jika tidak ada kesalahan dalam kode Anda, perintah g++ akan membuat file yang dapat dieksekusi bernama DisplayGreeting di direktori Anda.
Anda dapat menjalankan program menggunakan perintah berikut:
./DisplayGreeting
- Menekan tombol kembali menampilkan pesan di aplikasi. Melihat output, sepertinya Salam sedang dipotong, dan "????" ditampilkan sebagai gantinya.
HELLO FROM THE WINDBG TEAM. GOOD LUCK IN ALL OF YO????
Penelusuran Kesalahan DisplayGreeting
- Setelah kode siap dijalankan, kita dapat memulai aplikasi menggunakan gdbserver.
gdbserver localhost:1234 DisplayGreeting
Buka WinDbg, dan pilih "File / Sambungkan ke Debugger Jarak Jauh" dan masukkan string protokol untuk koneksi. Untuk contoh ini, kita akan menggunakan:
gdb:server=localhost,port=1234
.Setelah tersambung, output harus menunjukkan bahwa ia mendengarkan pada port 1234 dan koneksi debugging jarak jauh dibuat.
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
Seperti disebutkan sebelumnya, untuk beberapa lingkungan Linux perintah mungkin perlu dijalankan sebagai administrator, biasanya menggunakan sudo. Berhati-hatilah dengan mengaktifkan akses tingkat root administrator debugger dan hanya gunakan ini saat diperlukan.
Menambahkan jalur sumber dan simbol ke sesi debugger
Untuk mengatur titik henti dan melihat kode sumber dan variabel, atur simbol dan jalur sumber. Untuk informasi umum tentang mengatur jalur simbol, lihat Menggunakan Simbol.
Gunakan .sympath
untuk menambahkan jalur simbol ke sesi debugger. Dalam contoh ini, kode berjalan di lokasi ini di WSL Linux Ubuntu, untuk pengguna bernama Bob.
\\wsl$\Ubuntu\mnt\c\Users\Bob\
Di WSL, direktori ini memetakan ke lokasi OS Windows dari: C:\Users\Bob\
Jadi kedua perintah ini digunakan.
.sympath C:\Users\Bob\
.srcpath C:\Users\Bob\
Untuk informasi selengkapnya tentang sistem file WSL, lihat Izin File untuk WSL.
- Untuk mendapatkan manfaat dari simbol OS Linux tambahan, tambahkan simbol DebugInfoD menggunakan lokasi .sympath, seperti ini.
.sympath+ DebugInfoD*https://debuginfod.elfutils.org
- Juga didukung adalah pengunduhan otomatis sumber dari server DebugInfoD yang mendukung pengembalian jenis artefak tersebut. Untuk memanfaatkan ini, tambahkan server elfutils menggunakan .srcpath.
.srcpath+ DebugInfoD*https://debuginfod.elfutils.org
Menetapkan titik henti
Atur titik henti di utama aplikasi DisplayGreeting.
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
Gunakan opsi perintah Go atau menu untuk memulai ulang eksekusi kode.
Memuat kode sumber
Gunakan perintah .reload untuk memuat ulang simbol.
lm
Gunakan perintah untuk mengonfirmasi bahwa kami menjalankan aplikasi DisplayGreeting.
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
Setelah perintah memicu akses ke kode salam tampilan, perintah akan ditampilkan di WinDbg.
Gunakan perintah 'k' untuk mencantumkan tumpukan.
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```
Gunakan perintah dx untuk melihat salam variabel lokal. Perhatikan bahwa ukurannya adalah 50.
0:000> dx greeting
greeting : { size=50 } [Type: std::array<wchar_t, 50>]
[<Raw View>] [Type: std::array<wchar_t, 50>]
Lihat kode dan perhatikan bahwa 50, mungkin bukan ukuran yang cukup untuk pesan salam.
wchar_t const* const message = L"HELLO FROM THE WINDBG TEAM. GOOD LUCK IN ALL OF YOUR TIME TRAVEL
Konfirmasikan ini dengan memperluas variabel lokal untuk salam dan melihat bahwa salam dipotong.
Pemecahan masalah koneksi gdbserver
--debug
Gunakan opsi untuk menampilkan informasi tambahan di konsol gdbserver untuk mengumpulkan informasi selengkapnya tentang status koneksi. Misalnya untuk memulai server proses, gunakan perintah ini.
gdbserver --debug --multi localhost:1234