Stack Unwind – ARM Cortex M uzerinde Hata Analizi Yapmak

Ziyaret Sayisi 2382

ARM Cortex M uzerinde Hata Analizi Nasil Yapilir ?

Yazimiza giris yapmadan once ufak bir ARM bilgisi ile baslamayi uygun goruyorum. ARM firmasi yeni nesil islemci tasarimlari yapan ve bunlarin lisans haklarini baska firmalara satarak para kazanmakta olan bir firmadir. Ismi yine kendi tasarimlari olan;
1- Application Processor (A)
2- Real Time Processor (R)
3- Microcontroller Processor (M)
serilerinin bas harflerinin birlestirilmesi ile olusturulmustur.

A serisi islemciler bunyesinde cache, MMU, gelismis floating point uniteleri, yuksek saat frekansi (>600 MHz) gibi ozelliklere sahip olup uygulama sahalari, cep telefonundan, kisisel bilgisayarlara, yuksek hiza ihtiyac duyan ve coklu islemlere ozel olarak gelistirilmistir.

R serisi islemciler ise kesme (interrupt) birimlerinin ozellesmesi ve sahibi oldugu komut setinei bu dogrultuda iyi kullanabilmesi adina tasarlanmis, keskin zamanli isler tasarlanmistir.

M serisi islemciler ise mikrokontrollerler icin tasarlanmis olup, nispeten ufak olcekte ki MCUlarin cogunda kullanilmaktadir. Ornegin; Atmel ATSAM serisi, ST STM32 serisi, NXP LPC serisi vsvs.

Bu on girisi yaptiktan sonra biraz daha derinlere girmenin zamani gelmistir.

ARM Yazilan Kodu Nasil Calistirir ?

Genel olarak yazilan bir C kodu parser, object dosyasi ve linklenme asamalarindan gectikten sonra makine koduna donusturulerek orkestranizi yonetmenizi saglar. ARM icin bu durum farkli degildir. Fakat ARM icin makine kodu tarafinda birden cok seceneginiz bulunmaktadir. Yani guncel olarak 2 cesit assembly dili mevcuttur diyebiliriz kabaca. Bunlari soyle siralayabiliriz.

1- THUMB2 denilen makine kodunun farkli boyutlarda olabildigi genelde M serilerinde tercih edilen makine kodu,

2- ARM denilen makine kodlarinin sabit boyutlarda oldugu A serilerinde tercih edilen makine kodu.

Her ne kadar tercih edilir yazilsa da cesitli kaynaklarda; ARM modda calisan Cortex-M bulabileceginiz gibi THUMB2 modda calisan Cortex A’da gorebilirsiniz.
Her Cortex-M ARM modunu desteklemese de M4 lerde genelde destegi mevcuttur.

Bir C Derleyicisi Olarak GCC

GCC = GNU Compiler Collection, GCC gunumuzun en yaygin derleyicilerinden biridir. Neredeyse bircok mimariye destek veren genis altyapisi sayesinde, x86-64, ARM, sparc gibi mimariler icin rahat bir derleyici ortami sunmaktadir. Genel olarak yazimizin ilerleyen safhalarinda arm-none-eabi-gcc ozelinde bir cok parametreden soz edecegiz.

Sahada Hata Analizi Yapmak

Gelelim yazimizin temel konusuna bir gomulu sistem tasarladiniz. Diyelim ki bilinen butun pratikleri kodunuza uyguladiniz.

1- Kod yazim stili (Style checker)

2- Birim test (Unit Test)

3- Regresyon Testi (Regression Test)

4- Istisnai Durum Testi (Exceptional Analysis)
******
ve urununuzu guvenli sekilde sahaya gonderdiniz. Sahada olabileceklerden ne kadar eminiz veya Moore kanunun bize uygulanmasindan bizi ne koruyabilir. Cevap tahmin edilebilecegi gibi hicbir sey… Yazilan her kodda, uretilen her urunde sorun olabilir bu dogal bir durumdur. Onemli olan bu hatalara karsi ne derecede care bulabilecegimizdir. Debuggerlar her zaman yardimcimiz olsa da urunun fiziksel kosullarina bagli olarak her zaman debugger baglayip hatanin olusmasini beklemek zaman ve para acisindan bizleri her zaman olumlu etkilemeyebilir. Bu yazida Cortex M serisi islemciler icin hata aninda hatanin ciktigi fonksiyonu ve o fonksiyonu cagiran diger tum fonksiyonlari size veren kutuphanemizden biraz sizlere bahsedecegim.

Frame Pointer

Temel olarak yazimin basinda soyledigim gibi kutuphanemiz su an sadece THUMB2 moda destek vermektedir.  Bunun temel sebebini aslinda ARM ve THUMB2 mimarilerde kullanilan frame pointer denilen ozel bir yapinin farkliligi olusturmaktadir. Frame pointerlar calisma zamaninda fonksiyonlarin girisinde ve cikisinda kullandiginiz stack alanlarinin basi/sonunu gostermektedir. Boylelikle herhangi bir noktada frame pointer yardimiyla geriye donuk islem kontrolu yapabilmektedirler.

GCC’de bu opsiyonu aktif etmek icin -fno-omit-frame-pointer opsiyonunu gecmeniz gerekir.


Sekil 1. ARM Mod fonksiyon cagrilarinda frame pointer gecisi

ARM mod icin frame pointer bir onceki fonksiyonun kullandigi stack alaninin basini gostermektedir. Boylelikle hicbir ek bilgiye gerek kalmadan stack analizi yapmak epey basittir.

Gelelim THUMB2 moda, bu konuda derleyiciler arasinda fark bulunmaktadir. CLANG derleyicisinde 2017 den beri ARM mod gibi calistigindan ayni sekilde stack analizi yapmak mumkundur. Fakat GCC icin ayni ister, bakicilar(maintenaner) tarafindan uygun gorulmemistir. Bu sebeple GCC icin THUMB2 modda frame pointer asagida ki gibi davranmaktadir.

Edit: Thumb2 icin Clang-GCC tartismalari kaynak1 kaynak2

Sekil 2. THUMB2 – GCC fonksiyon cagrilarinda frame pointer gecisleri

Thumb2 modda R11 registeri yerine R7 registeri frame pointer olarak kullanilmaktadir. GCC icin farkli olarak bir onceki fonksiyonun frame’inin basini degil sonunu gostermektedir. Bu sebeple basitce geriye dogru stack frame i sarmak kolay degildir. Bu noktada imdadimiza daha genel bir debug yapisi olan unwind tablolari (unwind-table) yardimimiza yetismektedir. unwind-tables eklendiginde her bir fonksiyonun stack icin davranisini tanimlamaktadir.

Unwind-tables

Oncelikle GCC de bu opsiyonu aktiflestirmemiz gerekiyor. Bu sebeple derleyicimize -funwind-tables opsiyonunu gecmemiz gerekiyor. Bu tablolar ozel olarak her bir fonksiyonun giris esnasinda (epilogue) stacke atilan degiskenlerin ve registerlarin tutuldugu bir tablo listesidir. Linker script icerisinde tutulan su bolmeyi kullanir.

Bu bolum aslinda recete bolumudur. Yani bilgilerin tamamini icermeme durumu mevcuttur. Bu bolgede bulunan verinin yapisi su sekildedir.

address offset: tabloyu buldugunuz adresten ne kadar sonra veya once ilgili fonksiyonun baslangic adresinin oldugunu soyler.

inst: instructions yani yonergeler, bu offset olabilecegi gibi yonergenin ta kendisi de olabilir. gitlab’da bulunan kutuphanemizi inceleyebilirsiniz.

Bu tablo ile alakali en guzel seylerden biri linker asamasinda tum fonksiyonlar artan bir siralama ile bu tabloya yerlestirilirler, yani herhangi bir fonksiyonun baslangic adresini aramak istersek binary search metodu ile hizli bir sekilde arama yapip fonksiyonumuzun baslangic adresini ogrenebiliriz. Bu bilgi bizler icin onemli cunku calisma zamaninda herhangi adresin hangi fonksiyona ait oldugunu bilmek bir sonraki baslikta inceleyecegimiz GCC opsiyonu icin kritik oneme sahip…

Genis bilgi icin EHABI dokumani.

Fonksiyon Baslangic Adresinden Fonksiyon Ismi Ogrenme

GCC icin ozel bir opsiyon olan -mpoke-function-name parametresini derleyicimize gectigimiz zaman gelin assembly seviyesinde bize nasil bir cikti veriyor inceleyelim.

Assembly ciktimizda goruldugu gibi yazdigimiz fonksiyonun baslangic adresinin 1 WORD (4 byte) oncesine ozel bir buyulu kelime yerlestiriyor GCC. 0xFF000000 + (fonksiyon ismi uzunlugu). Tek yapmamiz gereken fonksiyonumuzun baslangic adresini alip 4 byte geriye gidip uzunlugu ogrenip bu stringi almak.

Sonuc

Artik derleyicimize -mpoke-function-name  -funwind-tables -fno-omit-frame-pointer opsiyonlarini gectik. Artik elimizde framelerimiz, recetelerimiz ve fonksiyon isimlerimiz mevcut. Gelelim cortex m serisinin istisnai durum (exception) karsisinda tamamen donanimsal olarak bize verdigi parametrelere, Cortex M referans dokumani uyarinca exception firlatildiginda donanimsal olarak o anki stack pointerin gosterdigi yere asagida ki registerlar aninda yuklenir.

Yani exceptioni yedigimiz adres, o adresi cagiranin adresi ve diger registerlar artik elimizdedir. Dikkat etmemiz gereken ise R7 yi yani Frame Pointer(FP) registerini bozmadan bir degisken icerisine hizlica depo etmemiz gerekir. Unutmayin standart bir C fonksiyonunu girisinde frame pointer modifiye edilecektir cunku bunu biz soyledik derleyiciye. Bu sebeple GCC nin bir baska harikasi olan “naked” ozelligi olan bir fonksiyon ile interrupti karsilayacagiz. Bu ozellik ile derleyiciye kesinlikle bu fonksiyonda olan bitene hicbir sey eklememesini veya cikarmamasini soyledik artik top tamamen bizde.

Kutuphanemiz yardimiyla artik kimin kimi cagirdigini kutuphanemizden basit bir fonksiyon cagrisi ile ogrenebilecegiz.

 

gitlab proje linki

 

Stack Unwind – ARM Cortex M uzerinde Hata Analizi Yapmak” Hakkında 3 Fikir

  1. Harika ve detaylı bir yazı olmuş. Türkçe kaynaklarda göremediğimiz kadar özgün olmuş.

    Gelelim sorulara

    Clang derleyicisinin davranışıyla ilgili verilen bilgiyle ilgili kaynak rica etsek?
    Ayrıca clang derleyici için uygun bir hard fault handler istiyoruz 🙄😊🙃

    1. Kaynak linki yazıya eklerim. Nereden aldığıma gelince direkt gcc mailing listten okudum. Çünkü bir contributor ekletmek için epey bir savaş vermiş…

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir