Yazan: M. Ali Vardar
<ali (at) linuxprogramlama.com>
- Yasal Açıklamalar
Bu belgenin,
GNU Debugger Kullanımı 1.0 sürümünün
telif hakkı © 2005 M. Ali Vardar'a aittir. Bu belgeyi, Free Software Foundation tarafından
yayınlanmış bulunan GNU Özgür Belgeleme Lisansının 1.1 sürümünün koşullarına
bağlı kalarak kopyalayabilir, dağıtabilir ve/veya
değiştirebilirsiniz. Bu Lisansın bir kopyasını
http://www.gnu.org/copyleft/fdl.html adresinde bulabilirsiniz.
BU BELGE “ÜCRETSİZ” OLARAK RUHSATLANDIĞI İÇİN, İÇERDİĞİ
BİLGİLER İÇİN İLGİLİ KANUNLARIN İZİN VERDİĞİ ÖLÇÜDE HERHANGİ BİR GARANTİ
VERİLMEMEKTEDİR. AKSİ YAZILI OLARAK BELİRTİLMEDİĞİ MÜDDETÇE TELİF HAKKI
SAHİPLERİ VE/VEYA BAŞKA ŞAHISLAR BELGEYİ “OLDUĞU GİBİ”,
AŞİKAR VEYA ZIMNEN, SATILABİLİRLİĞİ VEYA HERHANGİ BİR AMACA UYGUNLUĞU DA
DAHİL OLMAK ÜZERE HİÇBİR GARANTİ VERMEKSİZİN DAĞITMAKTADIRLAR. BİLGİNİN
KALİTESİ İLE İLGİLİ TÜM SORUNLAR SİZE AİTTİR. HERHANGİ BİR HATALI BİLGİDEN
DOLAYI DOĞABİLECEK OLAN BÜTÜN SERVİS, TAMİR VEYA DÜZELTME MASRAFLARI SİZE
AİTTİR.
İLGİLİ KANUNUN İCBAR ETTİĞİ DURUMLAR VEYA YAZILI ANLAŞMA HARİCİNDE HERHANGİ
BİR ŞEKİLDE TELİF HAKKI SAHİBİ VEYA YUKARIDA İZİN VERİLDİĞİ ŞEKİLDE BELGEYİ
DEĞİŞTİREN VEYA YENİDEN DAĞITAN HERHANGİ BİR KİŞİ, BİLGİNİN KULLANIMI VEYA
KULLANILAMAMASI (VEYA VERİ KAYBI OLUŞMASI, VERİNİN YANLIŞ HALE GELMESİ,
SİZİN VEYA ÜÇÜNCÜ ŞAHISLARIN ZARARA UĞRAMASI VEYA BİLGİLERİN BAŞKA BİLGİLERLE
UYUMSUZ OLMASI) YÜZÜNDEN OLUŞAN GENEL, ÖZEL, DOĞRUDAN YA DA DOLAYLI HERHANGİ
BİR ZARARDAN, BÖYLE BİR TAZMİNAT TALEBİ TELİF HAKKI SAHİBİ VEYA İLGİLİ KİŞİYE
BİLDİRİLMİŞ OLSA DAHİ, SORUMLU DEĞİLDİR.
Tüm telif hakları aksi özellikle belirtilmediği sürece sahibine aittir.
Belge içinde geçen herhangi bir terim, bir ticari isim ya da kuruma itibar
kazandırma olarak algılanmamalıdır. Bir ürün ya da markanın kullanılmış
olması ona onay verildiği anlamında görülmemelidir.
Ocak 2005
- Özet
Uygulamalarımızı geliştirme sırasında gerek sistemden olsun gerek yazılımcı tarafından olsun gelen bir takım sinyaller veya kesmeler veya hatalar yüzünden uygulamamızın çalışmasında kesilmeler olabilir. Bu
gibi durumları çoğu zaman tahmin edebiliyor olmak yeterli olmayabilir. Bu gibi durumlarda en büyük yardımcımız gdb olacaktır.
Uygulamalarımızı geliştirme sırasında gerek sistemden olsun gerek yazılımcı tarafından olsun gelen bir takım sinyaller veya kesmeler veya hatalar yüzünden uygulamamızın çalışmasında kesilmeler olabilir. Bu
gibi durumları çoğu zaman tahmin edebiliyor olmak yeterli olmayabilir. Bu gibi durumlarda en büyük yardımcımız gdb olacaktır. Linux sistemlerde yaygın olarak GBU debugger isimli uygulama kullanılır. Bu uygulama ile uygulamanızın kodu veya core dosyası incelenebilir. Öncelikle derleme işlemine bir bakalım.
$ gcc -g deneme.c -o deneme
Derleme işleminden sonra uygulamanın büyüklüğünün normal -g parametresiz
büyüklüğünden fazla olduğu görülecektir. Bu aşamadan sonra derlenen uygulama hata ayıklama işlemleri için gerekli olan açıklamaları da çalıştırılabilir dosyanın içerisine katmaktadır. Hata veren örnek bir uygulama yazalım. Örnek uygulama içerisinde değişiklik yapalım ve uygulamanın hata vermesini sağlayalım.
int main()
{
int a[5];
int i=0;
duzenle(a);
}
void duzenle(int a[])
{
int i;
for (i=0; i<10000; i++) a[i]=i;
}
Uygulamamız for (i=0; i<10000; i++) a[i]=i; satırında hata vermektedir. Çünkü bu satırda hafıza için ayrılmış olan 5 tamsayılık alanın 10000 nci değerine erişilmeye çalışılmaktadır. Uygulama ilk çalıştırıldığı anda "segmentation failed" (bölütleme başarısız) hatası verecektir. Bu kadar kısa bir kod içerisinde bunu bulmak sorun olmayacaktır. Ancak uygulamanın iç içe çağrılardan oluşan 100.000 satırlık bir uygulama olduğunu varsayarsanız bu gibi bir hatanın bulunması yazılımcıyı epey zorlayacaktır. Uygulamaya tekrar geri dönelim ve uygulamayı şimdi aşağıdaki şekilde çalıştıralım.
[root@linuxprogramlama 1]# gdb deneme
GNU gdb Red Hat Linux (5.1.90CVS-5)
Copyright 2002 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and
you are welcome to change it and/or distribute copies of it under
certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for
details.
This GDB was configured as "i386-redhat-linux"...
(gdb)
gdb ilk çalıştığı zaman yukarıdaki şekilde bir karşılama iletisi karşımıza çıkacaktır. Uygulama çalıştırılabilir dosyası gdb tarafından yüklenmiş
olacaktır. Uygulamayı r komutunu verelim ve karşımıza çıkan iletiye
bir bakalım.
(gdb) r
Starting program: /Projects/Kurs/1/deneme
Program received signal SIGSEGV, Segmentation fault.
0x08048418 in duzenle (a=0xbffff970) at deneme.c:12
12 for (i=0; i<9000; i++) a[i]=i;
İşte gdb hata veren satırımızı ekrana yazdı. Açıklamanın başında bulunan 12 rakamı bize uygulama kodumuz içerisinde hatayı veren satırdır. Şimdi hatanın oluşma süreçlerine bakalım bu amaçla bt (backtrace) komutunu kullanıyoruz.
(gdb) bt
#0 0x08048418 in duzenle (a=0xbffff970) at deneme.c:12
#1 0x080483e9 in main () at deneme.c:6
#2 0x0000000b in ?? ()
Cannot access memory at address 0xa
(gdb)
Böylelikle en sade halde uygulamamızda bulunan hataları izleme yöntemini gördük. Şimdi de daha etkin bir şekilde GNU debugger kullanabilmek amacıyla bir takım komutlara göz atalım.
list komutu bize hataya neden olan satırın bulunduğu komut listesini
verecektir.
(gdb) list
7 }
8
9 void duzenle(int a[])
10 {
11 int i;
12 for (i=0; i<9000; i++) a[i]=i;
13 }
(gdb)
Değişkenler hakkında bilgi almak için print komutu kullanılır.
(gdb) print a[5]
$2 = 5
(gdb)
Değişken türünü öğrenmek için whatis komutu kullanılır.
(gdb) whatis a
type = int *
Peki bir koşul oluşması durumunda istenen değişken bilgilerini almak istesek ne yapmamız gerekir? Bu amaçla uygulamanın çalışma anında durdurulmasını sağlayacak bir kırılma noktası yerleştirmeliyiz.
(gdb) break 12
Breakpoint 1 at 0x80483f6: file deneme.c, line 12.
(gdb) r
Starting program: /Projects/Kurs/1/deneme
Breakpoint 1, duzenle (a=0xbffff970) at deneme.c:12
12 for (i=0; i<9000; i++) a[i]=i;
(gdb) print i
$1 = 0
Yukarıda, 12. satıra bir kırılma noktası yerleştirdik ve o anki i değerine baktık. Diğer bir şartlı kırılma noktasına örnek ise;
(gdb) break 12 if i==5
Breakpoint 1 at 0x80483f6: file deneme.c, line 12.
(gdb)
Görüldüğü üzere i değişkeni 12. satırda 5 değerine ulaştığı an uygulama
kesilecektir. Makina dili kodlarını öğrenmek amacıyla verilen iki bellek arasını yazdırmak istersek:
(gdb) disas 0x63e4 0x6404
Dump of assembler code from 0x63e4 to 0x6404:
0x63e4 <builtin_init+5340>: ble 0x63f8 <builtin_init+5360>
0x63e8 <builtin_init+5344>: sethi %hi(0x4c00), %o0
0x63ec <builtin_init+5348>: ld [%i1+4], %o0
0x63f0 <builtin_init+5352>: b 0x63fc <builtin_init+5364>
0x63f4 <builtin_init+5356>: ld [%o0+4], %o0
0x63f8 <builtin_init+5360>: or %o0, 0x1a4, %o0
0x63fc <builtin_init+5364>: call 0x9288 <path_search>
0x6400 <builtin_init+5368>: nop
End of assembler dump.
Kesilmiş olan yerden devam etmek aşağıdaki gibi c komutunu vermek gerekir.
gdb'den çıkmak için quit veya q yazınız.
Aynı zamanda uygulamanız çöktüğünde oluşan core dosyasını da
şeklinde kullanarak hata veren yeren yeri bulabilirsiniz.