Was nützt dann GS?
x86_64-Linux-Kernel verwendet das GS-Register als effiziente Möglichkeit, Kernel-Space-Stack für Systemaufrufe zu erwerben.
Das GS-Register speichert die Basisadresse für den Bereich pro CPU. Um den Kernel-Space-Stack zu erhalten, in entry_SYSCALL_64
movq PER_CPU_VAR(cpu_current_top_of_stack), %rsp
Nach dem Erweitern von PER_CPU_VAR erhalten wir Folgendes:
movq %gs:cpu_current_top_of_stack, %rsp
Um Ihren fs:0 tatsächlich zu beantworten Frage:Die x86_64 ABI erfordert diese fs:0 enthält die Adresse, auf die von fs "gezeigt" wurde selbst. Das heißt fs:-4 lädt den unter fs:0 - 4 gespeicherten Wert . Diese Funktion ist notwendig, da Sie die Adresse, auf die fs zeigt, nicht einfach abrufen können ohne den Kernel-Code zu durchlaufen. Die Adresse unter fs:0 gespeichert haben macht die Arbeit mit lokalem Thread-Speicher viel effizienter.
Sie können dies in Aktion sehen, wenn Sie die Adresse einer lokalen Thread-Variablen nehmen:
static __thread int test = 0;
int *f(void) {
return &test;
}
int g(void) {
return test;
}
kompiliert zu
f:
movq %fs:0, %rax
leaq -4(%rax), %rax
retq
g:
movl %fs:-4, %eax
retq
i686 macht dasselbe, aber mit %gs . Auf aarch64 ist dies nicht erforderlich, da die Adresse aus dem tls-Register selbst gelesen werden kann.
In x86-64 gibt es 3 TLS-Einträge, zwei davon sind über FS und GS zugänglich, FS wird intern von glibc verwendet (in IA32 wird FS anscheinend von Wine und GS von glibc verwendet).
Glibc macht seinen TLS-Einstiegspunkt zu einem struct pthread das einige interne Strukturen zum Threading enthält. Glibc bezieht sich normalerweise auf einen struct pthread Variable als pd , vermutlich für pthread descriptor .
Auf x86-64 struct pthread beginnt mit einem tcbhead_t (Dies hängt von der Architektur ab, siehe Makros TLS_DTV_AT_TP und TLS_TCB_AT_TP ). Dieser Thread Control Block Header, AFAIU, enthält einige Felder, die benötigt werden, selbst wenn es einen einzelnen Thread gibt. Der DTV ist der dynamische Thread-Vektor und enthält Zeiger auf TLS-Blöcke für DSOs, die über dlopen() geladen werden . Vor oder nach dem TCB gibt es einen statischen TLS-Block für die ausführbare Datei und DSOs, die zur Ladezeit (des Programms) verknüpft sind. TCB und DTV werden ziemlich gut in Ulrich Dreppers TLS-Dokument erklärt (siehe Diagramme in Kapitel 3).