1 When building glibc PIE (which is not something upstream support),
2 several modifications are necessary to the glibc build process.
4 First, any syscalls in PIEs must be of the PIC variant, otherwise
5 textrels ensue. Then, any syscalls made before the initialisation
6 of the TLS will fail on i386, as the sysenter variant on i386 uses
7 the TLS, giving rise to a chicken-and-egg situation. This patch
8 defines a PIC syscall variant that doesn't use sysenter, even when the sysenter
9 version is normally used, and uses the non-sysenter version for the brk
10 syscall that is performed by the TLS initialisation. Further, the TLS
11 initialisation is moved in this case prior to the initialisation of
12 dl_osversion, as that requires further syscalls.
14 csu/libc-start.c: Move initial TLS initialization to before the
15 initialisation of dl_osversion, when INTERNAL_SYSCALL_NOSYSENTER is defined
17 csu/libc-tls.c: Use the no-sysenter version of sbrk when
18 INTERNAL_SYSCALL_NOSYSENTER is defined.
20 misc/sbrk.c: Define a no-sysenter version of sbrk, using the no-sysenter
21 version of brk - if INTERNAL_SYSCALL_NOSYSENTER is defined.
23 misc/brk.c: Define a no-sysenter version of brk if
24 INTERNAL_SYSCALL_NOSYSENTER is defined.
26 sysdeps/unix/sysv/linux/i386/sysdep.h: Define INTERNAL_SYSCALL_NOSYSENTER
27 Make INTERNAL_SYSCALL always use the PIC variant, even if not SHARED.
29 Patch by Kevin F. Quinn <kevquinn@gentoo.org>
31 --- glibc-2.10.1/csu/libc-start.c
32 +++ glibc-2.10.1/csu/libc-start.c
34 extern int __libc_multiple_libcs;
39 # include <dl-osinfo.h>
40 extern void __pthread_initialize_minimal (void);
43 _dl_aux_init (auxvec);
45 +# ifdef INTERNAL_SYSCALL_NOSYSENTER
46 + /* Do the initial TLS initialization before _dl_osversion,
47 + since the latter uses the uname syscall. */
48 + __pthread_initialize_minimal ();
50 # ifdef DL_SYSDEP_OSCHECK
51 if (!__libc_multiple_libcs)
57 +# ifndef INTERNAL_SYSCALL_NOSYSENTER
58 /* Initialize the thread library at least a bit since the libgcc
59 functions are using thread functions if these are available and
60 we need to setup errno. */
61 __pthread_initialize_minimal ();
64 /* Set up the stack checker's canary. */
65 uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard ();
66 --- glibc-2.10.1/csu/libc-tls.c
67 +++ glibc-2.10.1/csu/libc-tls.c
71 #include <sys/param.h>
77 #error makefile bug, this file is for static only
80 +#ifdef INTERNAL_SYSCALL_NOSYSENTER
81 +extern void *__sbrk_nosysenter (intptr_t __delta);
83 extern ElfW(Phdr) *_dl_phdr;
84 extern size_t _dl_phnum;
88 The initialized value of _dl_tls_static_size is provided by dl-open.c
89 to request some surplus that permits dynamic loading of modules with
93 + Where the normal sbrk would use a syscall that needs the TLS (i386)
94 + use the special non-sysenter version instead. */
96 tcb_offset = roundup (memsz + GL(dl_tls_static_size), tcbalign);
97 +# ifdef INTERNAL_SYSCALL_NOSYSENTER
98 + tlsblock = __sbrk_nosysenter (tcb_offset + tcbsize + max_align);
100 tlsblock = __sbrk (tcb_offset + tcbsize + max_align);
103 tcb_offset = roundup (tcbsize, align ?: 1);
104 +# ifdef INTERNAL_SYSCALL_NOSYSENTER
105 + tlsblock = __sbrk_nosysenter (tcb_offset + memsz + max_align
106 + + TLS_PRE_TCB_SIZE + GL(dl_tls_static_size));
108 tlsblock = __sbrk (tcb_offset + memsz + max_align
109 + TLS_PRE_TCB_SIZE + GL(dl_tls_static_size));
111 tlsblock += TLS_PRE_TCB_SIZE;
113 /* In case a model with a different layout for the TCB and DTV
114 --- glibc-2.10.1/misc/sbrk.c
115 +++ glibc-2.10.1/misc/sbrk.c
122 /* Defined in brk.c. */
123 extern void *__curbrk;
125 /* Extend the process's data space by INCREMENT.
126 If INCREMENT is negative, shrink data space by - INCREMENT.
127 Return start of new space allocated, or -1 for errors. */
128 +#ifdef INTERNAL_SYSCALL_NOSYSENTER
129 +/* This version is used by csu/libc-tls.c whem initialising the TLS
130 + if the SYSENTER version requires the TLS (which it does on i386).
131 + Obviously using the TLS before it is initialised is broken. */
132 +extern int __brk_nosysenter (void *addr);
134 +__sbrk_nosysenter (intptr_t increment)
138 + /* If this is not part of the dynamic library or the library is used
139 + via dynamic loading in a statically linked program update
140 + __curbrk from the kernel's brk value. That way two separate
141 + instances of __brk and __sbrk can share the heap, returning
142 + interleaved pieces of it. */
143 + if (__curbrk == NULL || __libc_multiple_libcs)
144 + if (__brk_nosysenter (0) < 0) /* Initialize the break. */
145 + return (void *) -1;
147 + if (increment == 0)
151 + if (__brk_nosysenter (oldbrk + increment) < 0)
152 + return (void *) -1;
158 __sbrk (intptr_t increment)
160 --- glibc-2.10.1/sysdeps/unix/sysv/linux/i386/brk.c
161 +++ glibc-2.10.1/sysdeps/unix/sysv/linux/i386/brk.c
164 weak_alias (__curbrk, ___brk_addr)
166 +#ifdef INTERNAL_SYSCALL_NOSYSENTER
167 +/* This version is used by csu/libc-tls.c whem initialising the TLS
168 + * if the SYSENTER version requires the TLS (which it does on i386).
169 + * Obviously using the TLS before it is initialised is broken. */
171 +__brk_nosysenter (void *addr)
173 + void *__unbounded newbrk;
175 + INTERNAL_SYSCALL_DECL (err);
176 + newbrk = (void *__unbounded) INTERNAL_SYSCALL_NOSYSENTER (brk, err, 1,
177 + __ptrvalue (addr));
183 + __set_errno (ENOMEM);
193 --- glibc-2.10.1/sysdeps/unix/sysv/linux/i386/sysdep.h
194 +++ glibc-2.10.1/sysdeps/unix/sysv/linux/i386/sysdep.h
196 /* The original calling convention for system calls on Linux/i386 is
198 #ifdef I386_USE_SYSENTER
200 +# if defined SHARED || defined __PIC__
201 # define ENTER_KERNEL call *%gs:SYSINFO_OFFSET
203 # define ENTER_KERNEL call *_dl_sysinfo
205 possible to use more than four parameters. */
206 #undef INTERNAL_SYSCALL
207 #ifdef I386_USE_SYSENTER
209 +# if defined SHARED || defined __PIC__
210 # define INTERNAL_SYSCALL(name, err, nr, args...) \
212 register unsigned int resultvar; \
214 : "0" (name), "i" (offsetof (tcbhead_t, sysinfo)) \
215 ASMFMT_##nr(args) : "memory", "cc"); \
217 +# define INTERNAL_SYSCALL_NOSYSENTER(name, err, nr, args...) \
219 + register unsigned int resultvar; \
222 + LOADARGS_NOSYSENTER_##nr \
223 + "movl %1, %%eax\n\t" \
225 + RESTOREARGS_NOSYSENTER_##nr \
226 + : "=a" (resultvar) \
227 + : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc"); \
228 + (int) resultvar; })
230 # define INTERNAL_SYSCALL(name, err, nr, args...) \
232 @@ -447,12 +459,20 @@
236 -# if defined I386_USE_SYSENTER && defined SHARED
237 +# if defined I386_USE_SYSENTER && ( defined SHARED || defined __PIC__ )
238 # define LOADARGS_1 \
239 "bpushl .L__X'%k3, %k3\n\t"
240 # define LOADARGS_5 \
241 "movl %%ebx, %4\n\t" \
243 +# define LOADARGS_NOSYSENTER_1 \
244 + "bpushl .L__X'%k2, %k2\n\t"
245 +# define LOADARGS_NOSYSENTER_2 LOADARGS_NOSYSENTER_1
246 +# define LOADARGS_NOSYSENTER_3 LOADARGS_3
247 +# define LOADARGS_NOSYSENTER_4 LOADARGS_3
248 +# define LOADARGS_NOSYSENTER_5 \
249 + "movl %%ebx, %3\n\t" \
250 + "movl %2, %%ebx\n\t"
252 # define LOADARGS_1 \
253 "bpushl .L__X'%k2, %k2\n\t"
254 @@ -474,11 +495,18 @@
256 #define RESTOREARGS_0
258 -# if defined I386_USE_SYSENTER && defined SHARED
259 +# if defined I386_USE_SYSENTER && ( defined SHARED || defined __PIC__ )
260 # define RESTOREARGS_1 \
261 "bpopl .L__X'%k3, %k3\n\t"
262 # define RESTOREARGS_5 \
264 +# define RESTOREARGS_NOSYSENTER_1 \
265 + "bpopl .L__X'%k2, %k2\n\t"
266 +# define RESTOREARGS_NOSYSENTER_2 RESTOREARGS_NOSYSENTER_1
267 +# define RESTOREARGS_NOSYSENTER_3 RESTOREARGS_3
268 +# define RESTOREARGS_NOSYSENTER_4 RESTOREARGS_3
269 +# define RESTOREARGS_NOSYSENTER_5 \
272 # define RESTOREARGS_1 \
273 "bpopl .L__X'%k2, %k2\n\t"