--- file_not_specified_in_diff +++ file_not_specified_in_diff @@ -, +, @@ --- csu/libc-start.c +++ csu/libc-start.c @@ -28,6 +28,7 @@ extern int __libc_multiple_libcs; #include +#include #ifndef SHARED # include extern void __pthread_initialize_minimal (void); @@ -129,6 +130,11 @@ # endif _dl_aux_init (auxvec); # endif +# ifdef INTERNAL_SYSCALL_NOSYSENTER + /* Do the initial TLS initialization before _dl_osversion, + since the latter uses the uname syscall. */ + __pthread_initialize_minimal (); +# endif # ifdef DL_SYSDEP_OSCHECK if (!__libc_multiple_libcs) { @@ -138,10 +144,12 @@ } # endif +# ifndef INTERNAL_SYSCALL_NOSYSENTER /* Initialize the thread library at least a bit since the libgcc functions are using thread functions if these are available and we need to setup errno. */ __pthread_initialize_minimal (); +# endif /* Set up the stack checker's canary. */ uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard (); --- csu/libc-tls.c +++ csu/libc-tls.c @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef SHARED @@ -29,6 +30,9 @@ #error makefile bug, this file is for static only #endif +#ifdef INTERNAL_SYSCALL_NOSYSENTER +extern void *__sbrk_nosysenter (intptr_t __delta); +#endif extern ElfW(Phdr) *_dl_phdr; extern size_t _dl_phnum; @@ -141,14 +145,26 @@ The initialized value of _dl_tls_static_size is provided by dl-open.c to request some surplus that permits dynamic loading of modules with - IE-model TLS. */ + IE-model TLS. + + Where the normal sbrk would use a syscall that needs the TLS (i386) + use the special non-sysenter version instead. */ #if TLS_TCB_AT_TP tcb_offset = roundup (memsz + GL(dl_tls_static_size), tcbalign); +# ifdef INTERNAL_SYSCALL_NOSYSENTER + tlsblock = __sbrk_nosysenter (tcb_offset + tcbsize + max_align); +# else tlsblock = __sbrk (tcb_offset + tcbsize + max_align); +# endif #elif TLS_DTV_AT_TP tcb_offset = roundup (tcbsize, align ?: 1); +# ifdef INTERNAL_SYSCALL_NOSYSENTER + tlsblock = __sbrk_nosysenter (tcb_offset + memsz + max_align + + TLS_PRE_TCB_SIZE + GL(dl_tls_static_size)); +# else tlsblock = __sbrk (tcb_offset + memsz + max_align + TLS_PRE_TCB_SIZE + GL(dl_tls_static_size)); +# endif tlsblock += TLS_PRE_TCB_SIZE; #else /* In case a model with a different layout for the TCB and DTV --- misc/sbrk.c +++ misc/sbrk.c @@ -18,6 +18,7 @@ #include #include #include +#include /* Defined in brk.c. */ extern void *__curbrk; @@ -29,6 +30,35 @@ /* Extend the process's data space by INCREMENT. If INCREMENT is negative, shrink data space by - INCREMENT. Return start of new space allocated, or -1 for errors. */ +#ifdef INTERNAL_SYSCALL_NOSYSENTER +/* This version is used by csu/libc-tls.c whem initialising the TLS + if the SYSENTER version requires the TLS (which it does on i386). + Obviously using the TLS before it is initialised is broken. */ +extern int __brk_nosysenter (void *addr); +void * +__sbrk_nosysenter (intptr_t increment) +{ + void *oldbrk; + + /* If this is not part of the dynamic library or the library is used + via dynamic loading in a statically linked program update + __curbrk from the kernel's brk value. That way two separate + instances of __brk and __sbrk can share the heap, returning + interleaved pieces of it. */ + if (__curbrk == NULL || __libc_multiple_libcs) + if (__brk_nosysenter (0) < 0) /* Initialize the break. */ + return (void *) -1; + + if (increment == 0) + return __curbrk; + + oldbrk = __curbrk; + if (__brk_nosysenter (oldbrk + increment) < 0) + return (void *) -1; + + return oldbrk; +} +#endif void * __sbrk (intptr_t increment) { --- sysdeps/unix/sysv/linux/i386/brk.c +++ sysdeps/unix/sysv/linux/i386/brk.c @@ -31,6 +31,30 @@ linker. */ weak_alias (__curbrk, ___brk_addr) +#ifdef INTERNAL_SYSCALL_NOSYSENTER +/* This version is used by csu/libc-tls.c whem initialising the TLS + * if the SYSENTER version requires the TLS (which it does on i386). + * Obviously using the TLS before it is initialised is broken. */ +int +__brk_nosysenter (void *addr) +{ + void *__unbounded newbrk; + + INTERNAL_SYSCALL_DECL (err); + newbrk = (void *__unbounded) INTERNAL_SYSCALL_NOSYSENTER (brk, err, 1, + __ptrvalue (addr)); + + __curbrk = newbrk; + + if (newbrk < addr) + { + __set_errno (ENOMEM); + return -1; + } + + return 0; +} +#endif int __brk (void *addr) { --- sysdeps/unix/sysv/linux/i386/sysdep.h +++ sysdeps/unix/sysv/linux/i386/sysdep.h @@ -187,7 +187,7 @@ /* The original calling convention for system calls on Linux/i386 is to use int $0x80. */ #ifdef I386_USE_SYSENTER -# ifdef SHARED +# if defined SHARED || defined __PIC__ # define ENTER_KERNEL call *%gs:SYSINFO_OFFSET # else # define ENTER_KERNEL call *_dl_sysinfo @@ -358,7 +358,7 @@ possible to use more than four parameters. */ #undef INTERNAL_SYSCALL #ifdef I386_USE_SYSENTER -# ifdef SHARED +# if defined SHARED || defined __PIC__ # define INTERNAL_SYSCALL(name, err, nr, args...) \ ({ \ register unsigned int resultvar; \ @@ -384,6 +384,18 @@ : "0" (name), "i" (offsetof (tcbhead_t, sysinfo)) \ ASMFMT_##nr(args) : "memory", "cc"); \ (int) resultvar; }) +# define INTERNAL_SYSCALL_NOSYSENTER(name, err, nr, args...) \ + ({ \ + register unsigned int resultvar; \ + EXTRAVAR_##nr \ + asm volatile ( \ + LOADARGS_NOSYSENTER_##nr \ + "movl %1, %%eax\n\t" \ + "int $0x80\n\t" \ + RESTOREARGS_NOSYSENTER_##nr \ + : "=a" (resultvar) \ + : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc"); \ + (int) resultvar; }) # else # define INTERNAL_SYSCALL(name, err, nr, args...) \ ({ \ @@ -447,12 +459,20 @@ #define LOADARGS_0 #ifdef __PIC__ -# if defined I386_USE_SYSENTER && defined SHARED +# if defined I386_USE_SYSENTER && ( defined SHARED || defined __PIC__ ) # define LOADARGS_1 \ "bpushl .L__X'%k3, %k3\n\t" # define LOADARGS_5 \ "movl %%ebx, %4\n\t" \ "movl %3, %%ebx\n\t" +# define LOADARGS_NOSYSENTER_1 \ + "bpushl .L__X'%k2, %k2\n\t" +# define LOADARGS_NOSYSENTER_2 LOADARGS_NOSYSENTER_1 +# define LOADARGS_NOSYSENTER_3 LOADARGS_3 +# define LOADARGS_NOSYSENTER_4 LOADARGS_3 +# define LOADARGS_NOSYSENTER_5 \ + "movl %%ebx, %3\n\t" \ + "movl %2, %%ebx\n\t" # else # define LOADARGS_1 \ "bpushl .L__X'%k2, %k2\n\t" @@ -474,11 +495,18 @@ #define RESTOREARGS_0 #ifdef __PIC__ -# if defined I386_USE_SYSENTER && defined SHARED +# if defined I386_USE_SYSENTER && ( defined SHARED || defined __PIC__ ) # define RESTOREARGS_1 \ "bpopl .L__X'%k3, %k3\n\t" # define RESTOREARGS_5 \ "movl %4, %%ebx" +# define RESTOREARGS_NOSYSENTER_1 \ + "bpopl .L__X'%k2, %k2\n\t" +# define RESTOREARGS_NOSYSENTER_2 RESTOREARGS_NOSYSENTER_1 +# define RESTOREARGS_NOSYSENTER_3 RESTOREARGS_3 +# define RESTOREARGS_NOSYSENTER_4 RESTOREARGS_3 +# define RESTOREARGS_NOSYSENTER_5 \ + "movl %3, %%ebx" # else # define RESTOREARGS_1 \ "bpopl .L__X'%k2, %k2\n\t"