7 Mart 2015 Cumartesi

Cocci İle Otomatikleştirilmiş Yama Oluşturma

Yaklaşık 3 hafta önce OPW'nin 10. turu başladı. OPW'yi merak edenler için, buraya bakabilirsiniz.

Yazının geri kalanında Coccinelle ile nasıl betik yazıldığını, yama hazırlarken bu betiğin dosyaya nasıl uygulandığını anlatacağım.

Coccinelle, otomatik olarak analiz yapan ve C kodunu yeniden yazabilen bir araç. Asıl yararı aynı düzeltmeleri her dosya için tek tek yapmak yerine, bir şablon oluşturup onunla birçok dosyayı tek seferde tarayayıp değiştirebilmesi. Desteklediği betik dilleri Python ve OCaml.  (sudo apt-get install coccinelle)

Betik yazarken genel yapı:

@@
degisken_tanımları
@@
Kurallar

İstersek ilk @@ işaretlerini @Betik_Adi@  şeklinde de kullanabiliriz. Bu kullanım uzun betikler yazarken okumayı kolaylaştırır.

Daha sonra kurallarda kullanacağımız değişkenleri tanımlamalıyız. Kural kısmı ise tamamen betik ile ne değiştirmek istediğimize bağlı.

Çok basit bir örnekle başlayalım:
Örnek1:

"foo.c" dosyasındaki C kodumuz şöyle olsun:
int main()
{
    foo();
    g(); 
    foo();
    g();
    foo();
}

Bu dosyadan foo() fonksiyonlarını kaldıralım. "-" ile kaldırılacak, "+" ile eklenecek alanı en genel şekliyle tanımlamalıyız.
foo.cocci dosyası:

@@
@@

- foo();
Betiği uygularken:

$ spatch -sp_file cocci_betigi -in_place uygulanacak_dosya_yolu


spatch yukarıdaki parametreleri ile betik dosyasını uygulayarak değişiklik olan yerleri gösterir.

Örnek2:
Aşağıdaki C kodunda kullanılan _cancel_timer_ex fonksiyonu yerine  del_timer_sync fonksiyonu kullanmak istersek elle tek tek değiştirmek yerine cocci betiği yazabiliriz.

C kodu: drivers/staging/rtl8712/os_intfs.c

Cocci betiği:
@@ expression x; @@

 - _cancel_timer_ex (&x);
+ del_timer_sync (&x);

Çıktı:




 

Örnek3: 
Gereksiz olan parantezleri kaldırmak için betik yazalım.
C kodu:



Cocci betiği:
@@
identifier i;
constant c;
type t;
expression e;
@@

t i =
-(e
+e
<<
-c);
+c;


Çıktı: Farkedildiği gibi değişecek satır(ların) kalıplarına göre tarif yapılıyor. Expression, constant, identifier gibi tipleri kullanırken değiştirmek istediğimiz satırdakilerle örtüştüğünden emin olmalıyız. Ayrıca yazdığımız betiğin, doğru olan satırlarının değiştirmiyor olmasına da dikkat etmeliyiz.

Örnek4:
Yazacağımız betikte Python kullanmak istersek @script:python@ diye belirtmemiz gerekiyor.
C dosyası:
int main () {
        foo(a0);
        bar();
}


Cocci betiği: 
@a@
identifier x;
@@
foo(x);
@script:python b@
x << a.x;
y;
z;
@@
print y
coccinelle.y = x
coccinelle.z = "something"
print y
@c@
identifier b.y;
identifier b.z;
identifier a.x;
@@
- bar();
+ matched_bar(y,z,x);


Çıktı:



Yazdığınız betik kurallara uygun mu, bir hatası var mı diye bakmak için:
$ spatch --parse-cocci deneme.cocci

Bu yazı sadece aklınızda bir fikir oluşması için giriş niteliğinde verilmiş örnekleri içeriyor. Coccinelle ile uğraştıkça daha karmaşık betikler yazılabilir. Daha fazla demo için buraya bakabilirsiniz. Kolay gelsin...

Hiç yorum yok:

Yorum Gönder