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.