Seperti yang Anda ketahui, kami dapat menggunakan GDB dan mengatur breakpoint pada kode kami untuk menghentikan sementara eksekusi untuk debugging.
Pertanyaan saya adalah, bagaimana GDB menghentikan proses dan membiarkan Anda melihat konten register menggunakan i r
misalnya. Bukankah register itu digunakan oleh proses OS lain secara konstan? bagaimana mereka tidak ditimpa?
Apakah ini hanya snapshot dari konten dan bukan data langsung?
Jawaban:
Ini sedikit berbeda dengan arsitektur, tetapi poin-poin penting berlaku hampir secara universal:
Servis interupsi menyebabkan keadaan CPU (termasuk register) disimpan ke memori sebelum menjalankan ISR, dan dipulihkan saat ISR keluar.
Jika rutinitas layanan interupsi menukar konten lokasi memori tempat register itu disimpan, ia dapat melakukan pengalih konteks . Setiap utas memiliki wilayah memori tempat registernya disimpan saat utas tidak berjalan.
Switch konteks dikontrol oleh penjadwal ulir yang memperhitungkan apakah utas menunggu I / O, sinkronisasi, prioritasnya, pengiriman sinyal, dll. Seringkali ada penghitungan sementara yang diperhitungkan.
Debugger dapat menambah jumlah penangguhan, yang menjamin utas tidak dapat dijalankan. Kemudian ia dapat memeriksa (dan mengubah) salinan register yang tersimpan di thread.
sumber
Selain informasi hebat oleh @BenVoigt, izinkan saya untuk membuat beberapa tambahan:
Breakpoint diatur oleh debugger dengan mengganti nilai kode mesin (instruksi atau bagian dari instruksi) dalam proses yang sedang dibebani dengan instruksi trap tertentu di lokasi dalam kode yang sesuai dengan jalur (sumber) yang diinginkan untuk dihancurkan. Instruksi perangkap khusus ini dimaksudkan untuk digunakan sebagai breakpoint - debugger mengetahui hal ini dan begitu juga sistem operasinya.
Ketika proses / utas yang sedang di-debug menyentuh instruksi trap, yang memicu proses yang dijelaskan oleh @Ben, yang mencakup setengah dari pertukaran konteks yang menangguhkan utas yang saat ini berjalan (yang termasuk menyimpan status CPU-nya ke memori) untuk kemungkinan dimulainya kembali nanti. Karena jebakan ini adalah jebakan breakpoint, sistem operasi menjaga proses debug ditangguhkan menggunakan mungkin mekanisme yang dijelaskan oleh @Ben, dan memberi tahu dan akhirnya melanjutkan debugger.
Debugger menggunakan panggilan sistem, kemudian, untuk mengakses keadaan tersimpan dari proses / utas ditangguhkan.
Untuk mengeksekusi (melanjutkan) baris kode yang rusak (yang sekarang memiliki instruksi jebakan khusus), debugger akan mengembalikan nilai kode mesin asli yang ditimpa dengan instruksi jebakan breakpoint, mungkin mengatur jebakan lain di tempat lain (misalnya jika satu langkah, atau pengguna membuat breakpoint baru), dan tandai proses / utas sebagai runnable, mungkin menggunakan mekanisme seperti yang dijelaskan @Ben.
Detail aktual dapat lebih rumit, karena mempertahankan breakpoint yang berjalan lama yang terkena berarti melakukan sesuatu seperti menukar breakpoint trap untuk kode nyata sehingga baris dapat berjalan, dan kemudian menukar breakpoint kembali ...
Seperti yang dijelaskan oleh @Ben, menggunakan fitur suspend / resume thread yang sudah ada (konteks switching / swapping multitasking ) yang memungkinkan prosesor untuk dibagikan oleh beberapa proses / utas menggunakan slicing waktu.
Keduanya. Karena thread yang melanda breakpoint ditangguhkan, snapshot dari data hidup (register CPU, dll ..) pada saat suspensi, dan yang menguasai otoritatif nilai-nilai register CPU untuk mengembalikan ke dalam prosesor seharusnya be benang dilanjutkan . Jika Anda menggunakan antarmuka pengguna debugger untuk membaca dan / atau mengubah register CPU (dari proses yang sedang di-debug) itu akan membaca dan / atau mengubah snapshot / master ini menggunakan panggilan sistem.
sumber
Sebenarnya, setidaknya dalam kebanyakan kasus, gdb sendiri tidak menghentikan eksekusi. Sebaliknya, gdb meminta OS, dan OS menghentikan eksekusi.
Awalnya mungkin tampak seperti perbedaan tanpa perbedaan - tapi jujur, memang ada perbedaan. Perbedaannya adalah ini: kemampuan itu sudah dibangun ke dalam OS yang khas, karena itu harus dapat menghentikan sementara dan memulai kembali pelaksanaan utas - ketika utas tidak dijadwalkan untuk berjalan (misalnya, diperlukan beberapa sumber daya yang saat ini tidak tersedia) OS harus menghentikannya sampai dijadwalkan untuk berjalan.
Untuk melakukan itu, OS biasanya memiliki blok memori yang disisihkan untuk setiap utas untuk menyimpan kondisi mesin saat ini. Ketika perlu menjeda utas, kondisi mesin saat ini disimpan di area itu. Ketika perlu melanjutkan utas, status mesin dipulihkan dari area itu.
Ketika debugger perlu menjeda utas, ia memiliki OS menjeda utas yang persis sama dengan alasan lain. Kemudian, untuk membaca status utas yang dijeda, debugger akan melihat status utas yang disimpan. Jika Anda memodifikasi status, debugger akan menulis ke status tersimpan, saat kemudian berlaku saat utas dilanjutkan.
sumber