2011-07-07 11 views
23

x86-64 mimarisinde, iki yazmaçın özel bir amacı vardır: FS ve GS. Linux 2.6'da *, FS kaydı iplik-yerel bilgi saklamak için kullanılıyor gibi görünüyor.Linux AMD64'de fs/gs registerları nasıl kullanılıyor?

  • Bu doğru mu?
  • Fs: 0'da ne saklanır? Bu içeriği açıklayan herhangi bir C yapısı var mı?
  • Bu durumda GS kullanımı nedir? x86-64 olarak

cevap

28

FS and GS ile bunların iki erişilebilir, 3 TLS entries vardır, FS (FS is used by Wine and GS by glibc görünüşte IA32 olarak) glibc'nin tarafından dahili olarak kullanılır.

Glibc, TLS giriş noktasını, iş parçacığı için bazı iç yapıları içeren struct pthread yapar. Glibc, büyük olasılıkla pthread tanımlayıcısı için pd olarak struct pthread değişkenini ifade eder. x86-64 günü

, bir tcbhead_t ile struct pthread başlar (Bu mimari bağlıdır, makro TLS_DTV_AT_TP ve TLS_TCB_AT_TP bakınız). Bu iş parçacığı denetim bloğu üstbilgisi, AFAIU, tek bir iş parçacığı olduğunda bile gerekli olan bazı alanları içerir. DTV, Dinamik Konu Vektörüdür ve dlopen() üzerinden yüklenen DSO'lar için TLS bloklarına işaretçiler içerir. TCB'den önce veya sonra, (program) yükleme süresinde bağlanan yürütülebilir ve DSO'lar için statik bir TLS bloğu vardır. TCB ve DTV Ulrich Drepper's TLS document'da oldukça iyi açıklanmıştır (bölüm 3'teki şemalara bakınız).

+1

FS, windows iş parçacığı bilgisini işaret etmek için x86 üzerinde win32 tarafından kullanılır - şarap sadece bunu eşleştiriyor. –

10

fs:0 sorunuzu yanıtlamak için: x86_64 ABI, fs:0'un "fs" un kendisi tarafından "noktaya getirilen" adresini içermesini gerektirir. Yani, fs:-4, fs:0 - 4'da depolanan değeri yükler. Bu özellik gereklidir, çünkü çekirdek kodundan geçmeden fs numaralı adresi kolayca gösteremezsiniz. fs:0 adresinde saklanan adresin bulunması, iş parçacığı yerel depolama ile çalışmayı çok daha verimli hale getirir. ama %gs ile aynı yapar

f: 
    movq %fs:0, %rax 
    leaq -4(%rax), %rax 
    retq 

g: 
    movl %fs:-4, %eax 
    retq 

i686 için

static __thread int test = 0; 

int *f(void) { 
    return &test; 
} 

int g(void) { 
    return test; 
} 

derler: Bir iş parçacığı yerel değişkenin adresini alırken

Sen eylem görebilirsiniz. Aarch64 üzerinde bu gerekli değildir, çünkü adres tls kaydının kendisinden okunabilir.