Laboratuvarlar / uygulama
"Debug bilgisini ayırmak, strip etmek ve geri bağlamak"
Debug verisini ayır, çalışma kopyasını strip et ve isimleri geri bağla.
Modern yazılım dağıtımlarında (Red Hat, Ubuntu, Debian), performans ve disk tasarrufu sağlamak amacıyla son kullanıcılara sembolleri ve DWARF hata ayıklama bilgileri temizlenmiş (stripped) ikili dosyalar sunulur. Ancak hata raporlama ve çökme analizi gerektiğinde, ayrı paketlerde tutulan (-dbgsym / debuginfo) hata ayıklama dosyaları ikiliye harici olarak geri bağlanır.
Bu laboratuvar; bir ikili dosyanın debug verisini objcopy ile bağımsız bir dosyaya ayırmayı, ana dosyayı strip etmeyi ve .gnu_debuglink mekanizması ile GDB'nin bu iki parçayı nasıl otomatik olarak birleştirdiğini adım adım inceler.
1. Deney Kodunun Hazırlanması#
Basit bir döngü ve yerel değişkenler içeren hesap.c dosyası:
#include <stdio.h>
int topla(int a, int b) {
int sonuc = a + b;
return sonuc;
}
int main(void) {
int x = 10;
int y = 20;
int toplam = topla(x, y);
printf("Toplam: %d\n", toplam);
return 0;
}
2. Programın Debug Sembolleriyle Derlenmesi#
Programı zengin DWARF formatında (-g3) derleyin:
gcc -Wall -Wextra -O0 -g3 hesap.c -o hesap
Dosya boyutunu ve sembol durumunu kontrol edin:
ls -lh hesap
file hesap
file çıktısında with debug_info, not stripped ifadesini görmelisiniz.
3. Debug Verisini Ayırma ve Strip Etme#
Standart GNU Binutils araçlarıyla debug verisini izole edin:
# 1. Debug bölümlerini bağımsız bir 'hesap.debug' dosyasına aktar:
objcopy --only-keep-debug hesap hesap.debug
# 2. Ana dosyayı tamamen strip et (tüm semboller ve debug bölümleri silinir):
strip --strip-debug --strip-unneeded hesap
# 3. Ana ikilinin içine debug dosyasının adını ve CRC32 sağlamasını göm:
objcopy --add-gnu-debuglink=hesap.debug hesap
Şimdi tekrar kontrol edin:
ls -lh hesap hesap.debug:hesapdosyasının boyutunun belirgin şekilde küçüldüğünü göreceksiniz.file hesap: Artıkstrippedolarak raporlanacaktır.readelf -S hesap:.debug_*bölümlerinin kaybolduğunu, yerine.gnu_debuglinkbölümünün eklendiğini görebilirsiniz.
readelf -x .gnu_debuglink hesap
Örnek çıktı:
Hex dump of section '.gnu_debuglink':
0x00000000 68657361 702e6465 62756700 00000000 hesap.debug.....
0x00000010 3a5b81c2 :[..
Son 4 bayt (3a5b81c2), hesap.debug dosyasının CRC32 kontrol toplamıdır. Eğer debug dosyası sonradan değiştirilirse GDB uyumsuzluk uyarısı verir.
4. GDB ile Otomatik Sembol Eşleştirmesini Doğrulamak#
Ana dosyayı GDB ile çalıştırın:
gdb -q ./hesap
GDB başlarken şu mesajı gösterecektir:
Reading symbols from ./hesap...
Reading symbols from /path/to/hesap.debug...
Artık dosya stripped olmasına rağmen kaynak kod satır numaraları ve fonksiyon adları kusursuzca görüntülenebilir:
(gdb) break topla
(gdb) run
(gdb) list
(gdb) print a
(gdb) print b
GDB, .gnu_debuglink içindeki dosya adını okumuş, aynı dizindeki veya /usr/lib/debug/ altındaki hesap.debug dosyasını bularak sembolleri belleğe yüklemiştir.
5. Build-ID Tabanlı Eşleştirme#
Modern sistemlerde dosya adına bağımlı kalmamak için Build-ID kullanılır (.note.gnu.build-id). GDB, bir ikilinin SHA-1 özetini alarak şu dizinde arama yapar:
/usr/lib/debug/.build-id/ab/1234567890abcdef.debug
Burada ilk 2 bayt dizin adı (ab), kalan baytlar ise debug dosyasının adıdır. Bu sayede dosya adı veya konumu değişse bile semboller daima doğru ikiliyle eşleşir.
İncelemeyi Derinleştir#
Sembolleri tamamen bulunmayan ikililerde analiz yöntemlerini kavramak için Stripped ELF rehberine geçin. Derleyici optimizasyonlarının kod yapısını nasıl değiştirdiğini görmek için Derleme farkları laboratuvarı uygulamasını yapın.