about summary refs log tree commit diff
path: root/src/env
diff options
context:
space:
mode:
authorRich Felker <dalias@aerifal.cx>2019-04-10 17:10:36 -0400
committerRich Felker <dalias@aerifal.cx>2019-04-10 17:10:36 -0400
commit22e5bbd0deadcbd767864bd714e890b70e1fe1df (patch)
tree4482da4b24c0e08b29769dad08bf800207db1227 /src/env
parente97681d6f2c44bf5fa9ecdd30607cb63c780062e (diff)
downloadmusl-22e5bbd0deadcbd767864bd714e890b70e1fe1df.tar.gz
musl-22e5bbd0deadcbd767864bd714e890b70e1fe1df.tar.xz
musl-22e5bbd0deadcbd767864bd714e890b70e1fe1df.zip
overhaul i386 syscall mechanism not to depend on external asm source
this is the first part of a series of patches intended to make
__syscall fully self-contained in the object file produced using
syscall.h, which will make it possible for crt1 code to perform
syscalls.

the (confusingly named) i386 __vsyscall mechanism, which this commit
removes, was introduced before the presence of a valid thread pointer
was mandatory; back then the thread pointer was setup lazily only if
threads were used. the intent was to be able to perform syscalls using
the kernel's fast entry point in the VDSO, which can use the sysenter
(Intel) or syscall (AMD) instruction instead of int $128, but without
inlining an access to the __syscall global at the point of each
syscall, which would incur a significant size cost from PIC setup
everywhere. the mechanism also shuffled registers/calling convention
around to avoid spills of call-saved registers, and to avoid
allocating ebx or ebp via asm constraints, since there are plenty of
broken-but-supported compiler versions which are incapable of
allocating ebx with -fPIC or ebp with -fno-omit-frame-pointer.

the new mechanism preserves the properties of avoiding spills and
avoiding allocation of ebx/ebp in constraints, but does it inline,
using some fairly simple register shuffling, and uses a field of the
thread structure rather than global data for the vdso-provided syscall
code address.

for now, the external __syscall function is refactored not to use the
old __vsyscall so it can be kept, but the intent is to remove it too.
Diffstat (limited to 'src/env')
-rw-r--r--src/env/__init_tls.c2
-rw-r--r--src/env/__libc_start_main.c2
2 files changed, 3 insertions, 1 deletions
diff --git a/src/env/__init_tls.c b/src/env/__init_tls.c
index f1874f2a..5f12500c 100644
--- a/src/env/__init_tls.c
+++ b/src/env/__init_tls.c
@@ -1,3 +1,4 @@
+#define SYSCALL_NO_TLS 1
 #include <elf.h>
 #include <limits.h>
 #include <sys/mman.h>
@@ -21,6 +22,7 @@ int __init_tp(void *p)
 	td->tid = __syscall(SYS_set_tid_address, &__thread_list_lock);
 	td->locale = &libc.global_locale;
 	td->robust_list.head = &td->robust_list.head;
+	td->sysinfo = __sysinfo;
 	td->next = td->prev = td;
 	return 0;
 }
diff --git a/src/env/__libc_start_main.c b/src/env/__libc_start_main.c
index 7c95f822..8fbe5262 100644
--- a/src/env/__libc_start_main.c
+++ b/src/env/__libc_start_main.c
@@ -28,7 +28,7 @@ void __init_libc(char **envp, char *pn)
 	libc.auxv = auxv = (void *)(envp+i+1);
 	for (i=0; auxv[i]; i+=2) if (auxv[i]<AUX_CNT) aux[auxv[i]] = auxv[i+1];
 	__hwcap = aux[AT_HWCAP];
-	__sysinfo = aux[AT_SYSINFO];
+	if (aux[AT_SYSINFO]) __sysinfo = aux[AT_SYSINFO];
 	libc.page_size = aux[AT_PAGESZ];
 
 	if (!pn) pn = (void*)aux[AT_EXECFN];