1 puan yazan GN⁺ 2025-10-26 | Henüz yorum yok. | WhatsApp'ta paylaş
  • Program çalıştırılmadan önce, çekirdeğin execve sistem çağrısı üzerinden süreci oluşturup başlatma sürecini inceleyen teknik bir analiz
  • Bu çağrı çalıştırılabilir dosya yolunu, argümanları ve ortam değişkenlerini iletir; çekirdek de buna dayanarak ELF biçimindeki çalıştırılabilir dosyayı yükler
  • ELF dosyası kod, veri, semboller ve dinamik bağlama bilgileri gibi unsurları içerir; çekirdek bunları yorumlayarak bellek eşlemeyi ve yığın başlatmayı gerçekleştirir
  • Ardından çekirdek denetimi _start giriş noktasına devreder; dile özgü runtime başlatıldıktan sonra ancak o zaman kullanıcı tanımlı main fonksiyonu çağrılır
  • Bu süreç, işletim sistemi, derleyici ve runtime arasındaki iş birliği yapısını gösterir ve sistem düzeyinde program yürütmenin nasıl gerçekleştiğini anlamak açısından önemlidir

Program çalıştırmanın başlangıç noktası: execve çağrısı

  • Linux'ta program çalıştırma execve sistem çağrısı ile başlar
    • execve(const char *filename, char *const argv[], char *const envp[]) biçiminde çalıştırılabilir dosya adı, argüman listesi ve ortam değişkenleri listesi iletilir
    • Çekirdek bunun üzerinden hangi programın hangi ortamda çalıştırılacağını belirler
  • Yüksek seviyeli dillerde bu çağrı genellikle standart kütüphanenin süreç çalıştırma API'si ile sarmalanır
    • Örnek: Rust'ın std::process::Command yapısı içeride execve çağırır
    • Kabuktaki PATH aramasına benzer şekilde, komut adını tam yola dönüştürme işlemi yapılır
  • Shebang(#!) içeren betiklerde çekirdek, belirtilen yorumlayıcıyı kullanarak programı çalıştırır
    • Örnek: #!/usr/bin/python3 → Python yorumlayıcısıyla çalıştırılır

ELF: çalıştırılabilir dosyanın yapısı

  • Linux'taki çalıştırılabilir dosyalar ELF(Executable and Linkable Format) biçimini izler
    • ELF; kod, veri, semboller ve yeniden konumlandırma bilgileri gibi unsurları içeren standart bir çalıştırılabilir dosya biçimidir
    • Diğer işletim sistemleri ise Mach-O(macOS), PE(Windows) gibi farklı biçimler kullanır
  • ELF başlığı dosyanın yapısı ve bellek yerleşimine dair bilgileri içerir
    • Örnek alanlar: ELF Magic, Class, Entry point address, Program headers, Section headers
    • Entry point address, programın ilk çalıştırılacağı komutun adresidir
  • Örnek ELF başlığında bunun RISC-V mimarisi için bir ELF32 çalıştırılabilir dosyası olduğu ve giriş noktasının 0x10358 adresi olarak belirlendiği görülür

ELF iç yapısı

  • ELF dosyası birden fazla bölümden(section) oluşur
    • .text: çalıştırılabilir kod
    • .data: başlatılmış global değişkenler
    • .bss: başlatılmamış global değişkenler
    • .plt: paylaşımlı kütüphane çağrıları için tablo
    • .symtab, .strtab: sembol ve dizge tabloları
  • PLT(Procedure Linkage Table), paylaşımlı kütüphane fonksiyon çağrılarını destekler
    • Örnek: libc içindeki printf, malloc gibi fonksiyonlar
    • ELF içindeki PT_INTERP bölümü, dinamik bağlayıcıyı(yorumlayıcıyı) belirtir
  • Çekirdek, ELF'yi okuyarak yüklenebilir bölümleri belleğe yerleştirir ve gerektiğinde ASLR, NX bit gibi güvenlik özelliklerini uygular

Sembol tablosu ve runtime bağlama

  • ELF'nin sembol tablosu(symtab), fonksiyon ve değişkenlerin adres bilgilerini içerir
    • Örnek girdiler: _start, main, __libc_start_main
    • Basit bir “Hello, World!” programı bile 2300'den fazla sembol içerebilir
  • Bunun büyük kısmı standart kütüphane ve runtime başlatma kodundan kaynaklanır
    • Çünkü musl veya glibc gibi libc uygulamaları bağlanmıştır
  • Çekirdek, ELF'nin her bölümünü yükledikten sonra denetimi yorumlayıcıya(dinamik bağlayıcıya) devreder
    • Yorumlayıcı yeniden konumlandırma(relocation), adres rastgeleleştirme(ASLR), çalıştırma izni ayarı(NX bit) gibi işlemleri yürütür

Yığın başlatma süreci

  • Çekirdek, program çalıştırılmadan önce yığını(stack) doğrudan kurmak zorundadır
    • Yığın; yerel değişkenler, fonksiyon çağrı çerçeveleri ve argüman aktarımı için kullanılır
  • execve çağrısında iletilen argv, envp yığına yerleştirilir
    • Program bu sayede komut satırı argümanlarına ve ortam değişkenlerine erişir
  • Çekirdek ayrıca ELF yardımcı vektörünü(auxv) de yığına ekler
    • Sayfa boyutu, ELF meta verileri ve sistem bilgileri dahil yaklaşık 30 öğe içerir
    • Örnek: AT_PAGESZ, bellek sayfası boyutunu belirtir (ör. 4KiB)
  • RISC-V öykünücü örneğinde yığın işaretçisi(sp), yüksek adreslerden başlatılır; argümanlar, ortam değişkenleri ve yardımcı vektör ters sırada yığına eklenir

Giriş noktası ve _start fonksiyonu

  • ELF'nin giriş noktası, _start fonksiyonunun adresi olarak belirlenir
    • _start, çekirdeğin denetimi devrettiği ilk kullanıcı alanı kodudur
  • Çoğu dil _start içinde önce runtime başlatmayı yapar, ardından main çağrılır
    • Örnek: Rust'ta std::rt::lang_start, C'de __libc_start_main
  • Rust örneğinde #![no_std], #![no_main] öznitelikleri kullanılarak runtime olmadan doğrudan _start tanımlanabilir
    • _start içinde yığından argc, argv, envp okunur ve main işaretçisi çağrılır
  • Dile özgü runtime; global kurucular, iş parçacığı yerel depolama ve istisna işleme gibi dile özel başlatma işlemlerini yürütür

main() çağrısına kadar olan genel akış

  • Tüm süreç şu şekilde özetlenebilir
    1. execve çağrılır → çekirdek ELF dosyasını yükler
    2. ELF yorumlanır → kod/veri bölümleri eşlenir, yorumlayıcı belirlenir
    3. Yığın kurulur → argümanlar, ortam değişkenleri ve yardımcı vektör kaydedilir
    4. Giriş noktası _start çalıştırılır
    5. Runtime başlatıldıktan sonra main() çağrılır
  • Bu adımlar dizisi, işletim sistemi çekirdeği, ELF biçimi ve dil runtime'ı arasındaki iş birliğini gösterir
  • Gerçek Linux çekirdeği adres alanı, süreç tablosu ve grup yönetimi gibi ek iç mantıklar da içerir; ancak bu yazı ondan önceki temel akışı açıklar

Sonuç ve düzeltme

  • main() öncesindeki yürütme süreci, çekirdek düzeyindeki başlatma ile runtime yapılandırmasının birleşimidir
  • Basit bir “Hello, World!” programı bile karmaşık ELF yapısı ve runtime başlatma adımlarından geçerek çalışır
  • Yazının ilk sürümünde bazı bölüm yükleme mantıkları çekirdeğe atfedilmişti; ancak gerçekte bunun ELF yorumlayıcısının görevi olduğu şeklinde düzeltme yapıldı
  • Bu analiz, sistem programlama, derleyiciler ve işletim sistemi mimarisini anlama açısından yararlı bir temel kaynak işlevi görür

Henüz yorum yok.

Henüz yorum yok.