Bir hata ayıklayıcının nasıl çalıştığını merak ediyorum. Özellikle zaten çalıştırılabilir çalıştırılabilir 'bağlı' olabilir. Derleyicinin kodu makine diline çevirdiğini anlıyorum, ancak hata ayıklayıcı neye bağlı olduğunu nasıl bilebilir?
Bir hata ayıklayıcının nasıl çalıştığını merak ediyorum. Özellikle zaten çalıştırılabilir çalıştırılabilir 'bağlı' olabilir. Derleyicinin kodu makine diline çevirdiğini anlıyorum, ancak hata ayıklayıcı neye bağlı olduğunu nasıl bilebilir?
Yanıtlar:
Bir hata ayıklayıcının nasıl çalıştığının ayrıntıları, hata ayıkladığınız ve işletim sisteminin ne olduğuna bağlı olacaktır. Windows'da yerel hata ayıklama için MSDN: Win32 Hata Ayıklama API'sı hakkında bazı ayrıntıları bulabilirsiniz .
Kullanıcı hata ayıklayıcıya hangi işlemin ekleneceğini ada veya işlem kimliğine göre söyler. Bu bir adsa, hata ayıklayıcı işlem kimliğini arar ve bir sistem çağrısı yoluyla hata ayıklama oturumu başlatır; Windows altında bu DebugActiveProcess olacaktır .
Hata ayıklayıcı eklendikten sonra, herhangi bir kullanıcı arayüzü için olduğu gibi bir olay döngüsüne girecektir, ancak pencereleme sisteminden gelen olaylar yerine, işletim sistemi hata ayıklanan işlemde ne olduğuna bağlı olarak olaylar üretecektir - örneğin bir istisna. Bkz. WaitForDebugEvent .
Hata ayıklayıcı, hedef işlemin sanal belleğini okuyabilir ve yazabilir ve hatta işletim sistemi tarafından sağlanan API'ler aracılığıyla kayıt değerlerini ayarlayabilir. Windows için hata ayıklama işlevleri listesine bakın .
Hata ayıklayıcı, adreslerden değişken adlarına ve kaynak kodundaki konumlara çevirmek için sembol dosyalarındaki bilgileri kullanabilir. Sembol dosyası bilgileri ayrı bir API grubudur ve işletim sisteminin temel bir parçası değildir. Windows'da bu, Debug Interface Access SDK'sı aracılığıyla yapılır .
Yönetilen bir ortamda (.NET, Java, vb.) Hata ayıklama yapıyorsanız, işlem tipik olarak benzer görünecektir, ancak sanal makine ortamı temel işletim sistemi yerine hata ayıklama API'sını sağladığı için ayrıntılar farklıdır.
Anladığım kadarıyla:
X86'daki yazılım kesme noktaları için, hata ayıklayıcı komutun ilk baytını CC
( int3
) ile değiştirir. Bu WriteProcessMemory
Windows ile yapılır . CPU bu talimatı aldığında ve çalıştırdığında int3
, bu işlem CPU'nun hata ayıklama istisnası oluşturmasına neden olur. İşletim sistemi bu kesmeyi alır, işlemin hata ayıklandığını fark eder ve hata ayıklayıcı sürecine kesme noktasının vurulduğunu bildirir.
Kesme noktası vurulduktan ve işlem durdurulduktan sonra, hata ayıklayıcı kesme noktaları listesine bakar ve yerine CC
oradaki baytla değiştirir . Ayıklayıcı setleri TF
, Tuzak Bayrak içinde EFLAGS
(değiştirerek CONTEXT
) ve işlemi devam eder. Bindirme Bayrağı CPU'nun bir INT 1
sonraki talimatta otomatik olarak tek adımlı bir istisna ( ) oluşturmasına neden olur .
Hata ayıklanan işlem bir dahaki sefere durduğunda, hata ayıklayıcı yeniden kesme noktası komutunun ilk baytını ile değiştirir CC
ve işlem devam eder.
Bu tam olarak tüm hata ayıklayıcılar tarafından nasıl uygulandığından emin değilim, ama bu mekanizma kullanarak kendini hata ayıklamayı başaran bir Win32 programı yazdım. Tamamen yararsız, ama eğitici.
Linux'ta bir işlemde hata ayıklama, ptrace (2) sistem çağrısı ile başlar . Bu makalede , ptrace
bazı basit hata ayıklama yapılarını uygulamak için nasıl kullanılacağı hakkında büyük bir öğretici vardır .
(2)
bize daha fazla (veya daha az) "ptrace bir sistem çağrısıdır" den bir şey söyleyeyim?
(2)
Kılavuz bölüm numarası. Manuel bölümlerin açıklaması için en.wikipedia.org/wiki/Man_page#Manual_sections adresine bakın .
ptrace
bir sistem çağrısı olduğunu söyler .
(2)
bize man 2 ptrace
doğru sayfayı yazabileceğimizi ve alabileceğimizi söyler - burada önemli değil, çünkü ptrace
anlaşılacak başka bir şey yok , ama Linux man printf
ile karşılaştırmak için man 3 printf
.
Windows işletim sistemindeyseniz bunun için harika bir kaynak John Robbins'in "Microsoft .NET ve Microsoft Windows için Uygulamalarda Hata Ayıklama" olacaktır:
(veya daha eski sürüm: "Uygulamalarda Hata Ayıklama" )
Kitapta, birkaç basit (ancak çalışan) hata ayıklayıcının kodunu içeren bir hata ayıklayıcının nasıl çalıştığı hakkında bir bölüm vardır.
Unix / Linux hata ayıklama ayrıntılarına aşina olmadığımdan, bu şeyler diğer işletim sistemleri için hiç geçerli olmayabilir. Ancak, çok karmaşık bir konuya giriş olarak, ayrıntıların ve API'ların olmasa bile kavramların herhangi bir işletim sistemine 'port' olması gerektiğini tahmin ediyorum.
Hata ayıklamayı anlamak için bir diğer değerli kaynak Intel CPU el kitabıdır (Intel® 64 ve IA-32 Architectures Yazılım Geliştirici El Kitabı). Bölüm 3A, bölüm 16'da, özel istisnalar ve donanım hata ayıklama kayıtları gibi hata ayıklama donanım desteğini tanıttı. Bu bölümden:
T (trap) bayrağı, TSS - TSS'sinde T bayrağı ayarlanmış bir göreve geçilmeye çalışıldığında bir hata ayıklama istisnası (#DB) oluşturur.
Window veya Linux'un bu bayrağı kullanıp kullanmadığından emin değilim, ancak bu bölümü okumak çok ilginç.
Umarım bu birine yardımcı olur.
Sanırım burada cevaplanması gereken iki ana soru var:
1. Hata ayıklayıcı bir istisna olduğunu nasıl bilebilir?
Hata ayıklanan bir işlemde kural dışı durum oluştuğunda, hata ayıklayıcı, hedef işlemde tanımlanan kullanıcı istisna işleyicilerine kural dışı duruma yanıt verme şansı verilmeden önce işletim sistemi tarafından bildirilir. Hata ayıklayıcı bu (birinci şans) kural dışı durum bildirimini işlememeyi seçerse, kural dışı durum gönderme dizisi daha da ilerler ve hedef iş parçacığına, bunu yapmak istiyorsa kural dışı durumu işlemek için bir şans verilir. SEH istisnası hedef işlem tarafından işlenmezse, hata ayıklayıcıya, hedef işlemde işlenmeyen bir özel durum oluştuğunu bildirmek için ikinci bir şans bildirimi adı verilen başka bir hata ayıklama olayı gönderilir. Kaynak
2. Hata ayıklayıcı bir kesme noktasında nasıl durduğunu nasıl bilir?
Basitleştirilmiş cevap : Programa bir kırılma noktası eklediğinizde, hata ayıklayıcı kodunuzu o noktada bir yazılım kesmesi olan int3 komutuyla değiştirir . Sonuç olarak program askıya alınır ve hata ayıklayıcı çağrılır.
Anladığım kadarıyla, bir uygulama veya DLL dosyasını derlediğinizde, ne derlerse işlevler ve değişkenleri temsil eden simgeler içerir.
Bir hata ayıklama derlemeniz olduğunda, bu semboller bir sürüm derlemesinden çok daha ayrıntılıdır, böylece hata ayıklayıcının size daha fazla bilgi vermesine izin verir. Hata ayıklayıcıyı bir işleme eklediğinizde, şu anda hangi işlevlere erişildiğine bakar ve buradan kullanılabilir tüm hata ayıklama simgelerini çözer (derlenmiş dosyanın iç kısımlarının nasıl göründüğünü bildiği için, bellekte ne olduğunu belirleyebilir , içeriğin, şamandıraların, dizelerin vb. içeriğiyle). İlk afişin dediği gibi, bu bilgiler ve bu sembollerin nasıl çalıştığı ortama ve dile bağlıdır.