Hata ayıklayıcılar hangi amaçlar için kullanılır?

Bu flood’da hata ayıklayıcıların (debugger) hangi amaçlar için ve nasıl kullanıldıklarını ele alacağız.

Bir uygulamanın çalışma zamanında yürüttüğü program kodlarını ve etkilediği değişkenleri gözlemleyebilmek için Hata Ayıklatıcı (debugger) adı verilen özel programlar kullanılır. Hata ayıklayıcı programlar sayesinde bir uygulamanın nasıl çalıştığı ile detaylı bilgilere ulaşılabilir. Birçok hata ayıklayıcı sunduğu breakpoint'ler sayesinde uygulamanın kaynak kodunun belirli bir satırında program akışının durdurulmasına olanak tanır. Akışı durdurulan programın tuttuğu değişkenlerin, parametrelerin, vb değerlerine ulaşılıp bu değerlerin beklenen değerlerle uyumlu olup olmadığı belirlenebilir. Yine birçok hata ayıklayıcı, hatası ayıklanan uygulamadaki kodun adım adım (single step) koşturulmasına ve kilit değişkenlerin her bir adımda değerlerini göstererek hataya yol açan satırın bulunmasına yardımcı olurlar.

Hata ayıklayıcıların en bilinen özelliği breakpoint'tir. Adlarından da anlaşılacağı üzere breakpoint'ler programın akışını durdurarak operatörün programın tuttuğu değerleri incelemesine olanak tanır. Bunun yanında birçok gelişmiş hata ayıklayıcı (gdb de dahil), programın tuttuğu global değişkenlerin, çağrılan bir prosedüre geçilen argümanların, vb program durdurulmadan (break) da okunabilmesine olanak tanır. Bu özelliğe tracepoint adı verilir çünkü istenen değişkenlerin değerleri programın çalışması durdurulmadan elde edilir. tracepoint ile elde edilen değerler genellikle bir circular buffer'a yazılır ve operatör tarafından okunur. tracepoint'ler üretim ortamında yapılan hata ayıklamalarıda sistemin durmasını gerektirmedikleri için breakpoint'lere oldukça güzel bir alternatif oluşturmaktadır.

tracepoint'ler, işe özelleştirilmiş ekipmanların kullanıldığı ve 7x24 hizmet verilmesi gereken telekomünikasyon, havacılık ve askeri uygulamalarda popüler olarak kullanılırlar. Buna ek olarak bazı problemler (örneğin race condition), program bir breakpoint ile durdurulduğunda ve adım adım çalıştırıldığında ortaya çıkmayabilir. Bu tür problemler tespit edilirken de tracepoint'ler tercih edilebilir. Her ne kadar tracepoint'lerle sistem durdurulmadan bazı bilgileri toplamak mümkün olsa da hata ayıklayıcının dahil olması ile programın çalışma karakteristiği değişmekte ve normalde açığa çıktığı halde tracepoint konulduğunda açığa çıkmayan problemler olabilmektedir. Bu tür durumlarda son çare olarak koda Debug Patch olarak adlandırılan, sadece problemi anlamaya yönelik kod parçaları eklenebilir.

Hata ayıklayıcı denilince öncelikli olarak akla gelmeyen ancak bazı durumlarda pek faydalı olabilen ve güçlü hata ayıklayıcılarda bulunan bir başka özellik de watchpoint ya da data breakpoint olarak adlandırılan ve bir hafıza alanı değiştiğinde programı durduran tipteki breakpoint'lerdir. Bu breakpoint'ler ile "sorumlulukların iyi dağıtılmadığı kod parçalarında" bir değişkeni değiştiren yığınçağırlar (callstack) tespit edilebilir. Bu özelliğin faydalı olduğu bir başka yer de aynı proses içerisinde koşan bir thread'in bir başka thread'in hafıza alanını hatalı bir şekilde bozması durumudur. Saldırgan (offending) thread tarafından bozulan masum memory alanına bir data breakpoint konularak saldırgan thread içerisindeki hatalı yığınçağır (callstack) yakalanıp kodda hatalı çalışan kısım tespit edilebilir.

Hata ayıklayıcılarda bulunan bir başka faydalı özellik ise koşullu breakpoint veya tracepoint'lerdir. Bir kod bloğunda durdurulmak istenen kodun ancak belirli durumlarda; örneğin, akışın ilgili satırdan 3. geçişinde veya akış ilgili satırdan geçerken bir değişken veya ifadenin değerine göre, vb durması istenebilir. Kod akışının yoğun olduğu satırlardaki hata ayıklamalarda bu özellik olmadan koddaki hatanın ayıklanması çok zor olabilir. Zamanlamaya bağlı ortaya çıkan hatalarda da ayıklama işleminde koşullu breakpoint'ler kullanılabilir.

Yukarıdakilere ek olarak hata ayıklayıcılar, breakpoint ile durdurulan programdaki global (heap) veya yerel (stack) değişkenlerin içeriklerinin elle değiştirilebilmesini de desteklemektedir. Bu özellik kullanılarak yaratılması zor senaryolar kolaylıkla simüle edilebilir.

Hata ayıklayıcılar, yukarıda sıralanan özellikleri (prosesi durdurmak, prosese ait değişkenleri okumak/güncellemek, vb) sağlayabilmek için işletim sistemi desteğine ihtiyacı duyarlar çünkü normal durumda aynı sistemde koşan iki prosesin birbirlerine ait memory alanını okuması ve bu alana yazması güvenlik açısından kısıtlanmıştır. Linux, bir prosesin debug edilebilmesi için ptrace adlı sistem çağrısını sunmaktadır. ptrace sistem çağrısı ile hata ayıklayıcı, hatası ayıklanan prosesi adım adım çalıştırabilir, proseste istediği memory adresine ulaşıp adreste değişiklik yapabilir. Hata ayıklayıcıların performanslı çalışabilmek için işletim sistemi desteğinin yanı sıra işlemci desteğine de ihtiyacı bulunmaktadır. İlerleyen flood'larda ptrace'in detaylarına ve modern hata ayıklayıcıların nasıl çalıştıklarına değineceğiz.