CLR yapıları ve temel konseptler
Merhabalar,
Bu yazımda CLR (Common Language Runtime) dll’inin runtime sınıf yapılarını nasıl oluşturduğu ile ilgili bilgi vermeyi amaçlıyorum. Öncelikle .Net uygulamalarını analiz ederken karşılaşacağınız temel kavramlara deyinmek istiyorum. Bu kavramlar için aşağıda kısa tanımlar yaptım:
Method Table (MT): .Net managed memory de yer alan tüm nesnelerde, nesnenin kendi method tablosuna bir referans bulunur. Method tablosunda (C++ daki VTable gibi) ise o nesneye ait fonksiyonlar yer almaktadır (MD - Method descriptor).
Domain: Bir process'de assembly dosyalarının yüklenme hiyerarşisi şu şekildedir: Process->AppDomain->Assembly->Module. Process içerisinde birden fazla AppDomain olabilir. Aynı şekilde bir AppDomain içerisinde ise birden fazla Assembly bulunabilir. Domain'e yüklenen assembly'leri görmek için !dumpdomain gibi komutları kullanabilirsiniz.
Threadler: Threadler anlık olarak belirli bir AppDomain içerisinde koşarlar. Fakat aynı thread başka bir AppDomain'e geçiş yapabilir. CLR'ın kendine özgü bir threadpool yapısı vardır. Örneğin; WorkerThread'ler asıl işi yaparken, diğer threadler senkronizasyon, IO gibi işlevleri yürütürler. Bir .net uygulamasının dump dosyasında Thread'lerle ilgili bilgi almak istiyorsanız Psscor'un '!threads' komutunu kullanabilirsiniz.
Garbage Collection: .Net uygulamalarında Managed Heap’te yaratılan nesneler, kullanıldıktan sonra belirli aralıklarla temizlenirler. Nesnelerin temizlenmesi için koşul, nesnenin üst referansının (‘Parent’) almamış olmasıdır. Her bir temizleme (GC) esnasında referansını yitirmeyen nesneler bir sonraki Jenerasyon’a aktarılır. Şuanda ‘0’ , ‘1’ ve ‘2’ Olmak üzere üç ayrı Jenerasyon vardır. Örneğin Gen#0 da bulunan bir nesne temizlenemezse Gen#1’e aynı şekilde Gen#1’deki nesne temizlenemez ise Gen#2 Heap ‘e aktarılır. Son olarak 85 Kb’dan büyük nesnelerin tutulduğu LOH (Large Object Heap) ‘ten bahsetmek gerekiyor.
Exceptionlar: CLR tarafından fırlatılan Exception’lar son olarak Native çağrı olan RaiseException() methodunu çağırırlar. Fırlatılan Exception kodu .Net 1.0 – 3. 5 için ‘E0434F4D’ , .Net 4 içinse ‘E0434352’ dir. Managed memory'deki Exceptionları görmek için !dae komutunu kullanabilirsiniz.
Şimdi ise managed bir CLR objesinin ilgili Method yapıları ile ilişkisini anlamak için Windbg kullanarak ufak bir çalışma yapalım. Diyelimki dump analizi sırasında elimizde bir tane CLR objesinin adresi var, ve bu objeyi !do (dumpobject) komutu ile dump ettik. Aşağıdaki resimde Objeden, method tablosuna, method tablosundan method tanımlayıcılarına doğru nasıl gidebileceğimizi anlatmaya çalıştım.
‘dd’ ('dump double word', dword şeklinde memory içeriğini görüntüler) komutu dışında kullandığım komutlar Psscor komutları. ‘dd’ komutu ile memory içeriğini dökmemin sebebi aslında Psscor’un ilgili memory bloğunu bizim istediğimiz şekilde yorumluyor olduğunu göstermek. Görüldüğü gibi tüm HttpWebRequest nesnelerinde ilgili 'method table' yapısına referans bulunuyor. 'Method table' yapısı üzerinden ise kod bloklarına erişiyoruz. (Resmin büyük halini görmek için üzerine tıklayabilirsiniz):
Yukarıda belirttiğim Managed .Net objesinin 'Memory' gösteriminde ('dd 00000001812d3ab0 - 4 ') objenin bulunduğu adresten 4 byte geriden başlayan bir 'syncBlk' yapısı olduğunu görüyorsunuz. Bu yapı 'SyncTableEntry' tablosuna bir index tutar. 'SyncTableEntry' tablosundan da ilgili SyncBlock nesnesine referans tutulmaktadır. synBlock nesneleri obje ile ilgili bir takım fonksiyonalite'lerin kullanılmasını sağlar. (Psscor eklentisinde tüm syncBlk nesnelerini dökmek için '!syncblk -all' komutunu kullanabilirsiniz)
Daha detaylı bilgi için ‘.Net Framework Internals’ makalesini inceleyebilirsiniz. Aşağıda bu makaleden aldığım şemada, yukarıda gösterdiğim ilişkileri, daha genel bir şekilde görebilirsiniz.
Windbg ve Psscor kurulumu ile ilgili olarak önceki makalemi inceleyebilirsiniz.
İyi çalışmalar,
Mert Öztürk