1 /* Copyright (C) 2001-2022 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3 
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8 
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <https://www.gnu.org/licenses/>.  */
17 
18 #ifndef _LINUX_X86_64_SYSDEP_H
19 #define _LINUX_X86_64_SYSDEP_H 1
20 
21 /* There is some commonality.  */
22 #include <sysdeps/unix/sysv/linux/sysdep.h>
23 #include <sysdeps/unix/x86_64/sysdep.h>
24 #include <tls.h>
25 
26 /* Defines RTLD_PRIVATE_ERRNO.  */
27 #include <dl-sysdep.h>
28 
29 /* For Linux we can use the system call table in the header file
30 	/usr/include/asm/unistd.h
31    of the kernel.  But these symbols do not follow the SYS_* syntax
32    so we have to redefine the `SYS_ify' macro here.  */
33 #undef SYS_ify
34 #define SYS_ify(syscall_name)	__NR_##syscall_name
35 
36 #ifdef __ASSEMBLER__
37 
38 /* Linux uses a negative return value to indicate syscall errors,
39    unlike most Unices, which use the condition codes' carry flag.
40 
41    Since version 2.1 the return value of a system call might be
42    negative even if the call succeeded.	 E.g., the `lseek' system call
43    might return a large offset.	 Therefore we must not anymore test
44    for < 0, but test for a real error by making sure the value in %eax
45    is a real error number.  Linus said he will make sure the no syscall
46    returns a value in -1 .. -4095 as a valid result so we can savely
47    test with -4095.  */
48 
49 /* We don't want the label for the error handle to be global when we define
50    it here.  */
51 # undef SYSCALL_ERROR_LABEL
52 # ifdef PIC
53 #  undef SYSCALL_ERROR_LABEL
54 #  define SYSCALL_ERROR_LABEL 0f
55 # else
56 #  undef SYSCALL_ERROR_LABEL
57 #  define SYSCALL_ERROR_LABEL syscall_error
58 # endif
59 
60 /* PSEUDO and T_PSEUDO macros have 2 extra arguments for unsigned long
61    int arguments.  */
62 # define PSEUDOS_HAVE_ULONG_INDICES 1
63 
64 # ifndef SYSCALL_ULONG_ARG_1
65 #  define SYSCALL_ULONG_ARG_1 0
66 #  define SYSCALL_ULONG_ARG_2 0
67 # endif
68 
69 # undef	PSEUDO
70 # if SYSCALL_ULONG_ARG_1
71 #  define PSEUDO(name, syscall_name, args, ulong_arg_1, ulong_arg_2) \
72   .text;							      \
73   ENTRY (name)							      \
74     DO_CALL (syscall_name, args, ulong_arg_1, ulong_arg_2);	      \
75     cmpq $-4095, %rax;						      \
76     jae SYSCALL_ERROR_LABEL
77 # else
78 #  define PSEUDO(name, syscall_name, args) \
79   .text;							      \
80   ENTRY (name)							      \
81     DO_CALL (syscall_name, args, 0, 0);				      \
82     cmpq $-4095, %rax;						      \
83     jae SYSCALL_ERROR_LABEL
84 # endif
85 
86 # undef	PSEUDO_END
87 # define PSEUDO_END(name)						      \
88   SYSCALL_ERROR_HANDLER							      \
89   END (name)
90 
91 # undef	PSEUDO_NOERRNO
92 # if SYSCALL_ULONG_ARG_1
93 #  define PSEUDO_NOERRNO(name, syscall_name, args, ulong_arg_1, ulong_arg_2) \
94   .text;							      \
95   ENTRY (name)							      \
96     DO_CALL (syscall_name, args, ulong_arg_1, ulong_arg_2)
97 # else
98 #  define PSEUDO_NOERRNO(name, syscall_name, args) \
99   .text;							      \
100   ENTRY (name)							      \
101     DO_CALL (syscall_name, args, 0, 0)
102 # endif
103 
104 # undef	PSEUDO_END_NOERRNO
105 # define PSEUDO_END_NOERRNO(name) \
106   END (name)
107 
108 # define ret_NOERRNO ret
109 
110 # undef	PSEUDO_ERRVAL
111 # if SYSCALL_ULONG_ARG_1
112 #  define PSEUDO_ERRVAL(name, syscall_name, args, ulong_arg_1, ulong_arg_2) \
113   .text;							\
114   ENTRY (name)							\
115     DO_CALL (syscall_name, args, ulong_arg_1, ulong_arg_2);	\
116     negq %rax
117 # else
118 #  define PSEUDO_ERRVAL(name, syscall_name, args) \
119   .text;							\
120   ENTRY (name)							\
121     DO_CALL (syscall_name, args, 0, 0);				\
122     negq %rax
123 # endif
124 
125 # undef	PSEUDO_END_ERRVAL
126 # define PSEUDO_END_ERRVAL(name) \
127   END (name)
128 
129 # define ret_ERRVAL ret
130 
131 # if defined PIC && RTLD_PRIVATE_ERRNO
132 #  define SYSCALL_SET_ERRNO			\
133   lea rtld_errno(%rip), %RCX_LP;		\
134   neg %eax;					\
135   movl %eax, (%rcx)
136 # else
137 #  if IS_IN (libc)
138 #   define SYSCALL_ERROR_ERRNO __libc_errno
139 #  else
140 #   define SYSCALL_ERROR_ERRNO errno
141 #  endif
142 #  define SYSCALL_SET_ERRNO			\
143   movq SYSCALL_ERROR_ERRNO@GOTTPOFF(%rip), %rcx;\
144   neg %eax;					\
145   movl %eax, %fs:(%rcx);
146 # endif
147 
148 # ifndef PIC
149 #  define SYSCALL_ERROR_HANDLER	/* Nothing here; code in sysdep.S is used.  */
150 # else
151 #  define SYSCALL_ERROR_HANDLER			\
152 0:						\
153   SYSCALL_SET_ERRNO;				\
154   or $-1, %RAX_LP;				\
155   ret;
156 # endif	/* PIC */
157 
158 /* The Linux/x86-64 kernel expects the system call parameters in
159    registers according to the following table:
160 
161     syscall number	rax
162     arg 1		rdi
163     arg 2		rsi
164     arg 3		rdx
165     arg 4		r10
166     arg 5		r8
167     arg 6		r9
168 
169     The Linux kernel uses and destroys internally these registers:
170     return address from
171     syscall		rcx
172     eflags from syscall	r11
173 
174     Normal function call, including calls to the system call stub
175     functions in the libc, get the first six parameters passed in
176     registers and the seventh parameter and later on the stack.  The
177     register use is as follows:
178 
179      system call number	in the DO_CALL macro
180      arg 1		rdi
181      arg 2		rsi
182      arg 3		rdx
183      arg 4		rcx
184      arg 5		r8
185      arg 6		r9
186 
187     We have to take care that the stack is aligned to 16 bytes.  When
188     called the stack is not aligned since the return address has just
189     been pushed.
190 
191 
192     Syscalls of more than 6 arguments are not supported.  */
193 
194 # undef	DO_CALL
195 # define DO_CALL(syscall_name, args, ulong_arg_1, ulong_arg_2) \
196     DOARGS_##args				\
197     ZERO_EXTEND_##ulong_arg_1			\
198     ZERO_EXTEND_##ulong_arg_2			\
199     movl $SYS_ify (syscall_name), %eax;		\
200     syscall;
201 
202 # define DOARGS_0 /* nothing */
203 # define DOARGS_1 /* nothing */
204 # define DOARGS_2 /* nothing */
205 # define DOARGS_3 /* nothing */
206 # define DOARGS_4 movq %rcx, %r10;
207 # define DOARGS_5 DOARGS_4
208 # define DOARGS_6 DOARGS_5
209 
210 # define ZERO_EXTEND_0 /* nothing */
211 # define ZERO_EXTEND_1 /* nothing */
212 # define ZERO_EXTEND_2 /* nothing */
213 # define ZERO_EXTEND_3 /* nothing */
214 # define ZERO_EXTEND_4 /* nothing */
215 # define ZERO_EXTEND_5 /* nothing */
216 # define ZERO_EXTEND_6 /* nothing */
217 
218 #else	/* !__ASSEMBLER__ */
219 
220 /* Registers clobbered by syscall.  */
221 # define REGISTERS_CLOBBERED_BY_SYSCALL "cc", "r11", "cx"
222 
223 /* NB: This also works when X is an array.  For an array X,  type of
224    (X) - (X) is ptrdiff_t, which is signed, since size of ptrdiff_t
225    == size of pointer, cast is a NOP.   */
226 #define TYPEFY1(X) __typeof__ ((X) - (X))
227 /* Explicit cast the argument.  */
228 #define ARGIFY(X) ((TYPEFY1 (X)) (X))
229 /* Create a variable 'name' based on type of variable 'X' to avoid
230    explicit types.  */
231 #define TYPEFY(X, name) __typeof__ (ARGIFY (X)) name
232 
233 #undef INTERNAL_SYSCALL
234 #define INTERNAL_SYSCALL(name, nr, args...)				\
235 	internal_syscall##nr (SYS_ify (name), args)
236 
237 #undef INTERNAL_SYSCALL_NCS
238 #define INTERNAL_SYSCALL_NCS(number, nr, args...)			\
239 	internal_syscall##nr (number, args)
240 
241 #undef internal_syscall0
242 #define internal_syscall0(number, dummy...)				\
243 ({									\
244     unsigned long int resultvar;					\
245     asm volatile (							\
246     "syscall\n\t"							\
247     : "=a" (resultvar)							\
248     : "0" (number)							\
249     : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
250     (long int) resultvar;						\
251 })
252 
253 #undef internal_syscall1
254 #define internal_syscall1(number, arg1)					\
255 ({									\
256     unsigned long int resultvar;					\
257     TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\
258     register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\
259     asm volatile (							\
260     "syscall\n\t"							\
261     : "=a" (resultvar)							\
262     : "0" (number), "r" (_a1)						\
263     : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
264     (long int) resultvar;						\
265 })
266 
267 #undef internal_syscall2
268 #define internal_syscall2(number, arg1, arg2)				\
269 ({									\
270     unsigned long int resultvar;					\
271     TYPEFY (arg2, __arg2) = ARGIFY (arg2);			 	\
272     TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\
273     register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;			\
274     register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\
275     asm volatile (							\
276     "syscall\n\t"							\
277     : "=a" (resultvar)							\
278     : "0" (number), "r" (_a1), "r" (_a2)				\
279     : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
280     (long int) resultvar;						\
281 })
282 
283 #undef internal_syscall3
284 #define internal_syscall3(number, arg1, arg2, arg3)			\
285 ({									\
286     unsigned long int resultvar;					\
287     TYPEFY (arg3, __arg3) = ARGIFY (arg3);			 	\
288     TYPEFY (arg2, __arg2) = ARGIFY (arg2);			 	\
289     TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\
290     register TYPEFY (arg3, _a3) asm ("rdx") = __arg3;			\
291     register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;			\
292     register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\
293     asm volatile (							\
294     "syscall\n\t"							\
295     : "=a" (resultvar)							\
296     : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3)			\
297     : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
298     (long int) resultvar;						\
299 })
300 
301 #undef internal_syscall4
302 #define internal_syscall4(number, arg1, arg2, arg3, arg4)		\
303 ({									\
304     unsigned long int resultvar;					\
305     TYPEFY (arg4, __arg4) = ARGIFY (arg4);			 	\
306     TYPEFY (arg3, __arg3) = ARGIFY (arg3);			 	\
307     TYPEFY (arg2, __arg2) = ARGIFY (arg2);			 	\
308     TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\
309     register TYPEFY (arg4, _a4) asm ("r10") = __arg4;			\
310     register TYPEFY (arg3, _a3) asm ("rdx") = __arg3;			\
311     register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;			\
312     register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\
313     asm volatile (							\
314     "syscall\n\t"							\
315     : "=a" (resultvar)							\
316     : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4)		\
317     : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
318     (long int) resultvar;						\
319 })
320 
321 #undef internal_syscall5
322 #define internal_syscall5(number, arg1, arg2, arg3, arg4, arg5)	\
323 ({									\
324     unsigned long int resultvar;					\
325     TYPEFY (arg5, __arg5) = ARGIFY (arg5);			 	\
326     TYPEFY (arg4, __arg4) = ARGIFY (arg4);			 	\
327     TYPEFY (arg3, __arg3) = ARGIFY (arg3);			 	\
328     TYPEFY (arg2, __arg2) = ARGIFY (arg2);			 	\
329     TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\
330     register TYPEFY (arg5, _a5) asm ("r8") = __arg5;			\
331     register TYPEFY (arg4, _a4) asm ("r10") = __arg4;			\
332     register TYPEFY (arg3, _a3) asm ("rdx") = __arg3;			\
333     register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;			\
334     register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\
335     asm volatile (							\
336     "syscall\n\t"							\
337     : "=a" (resultvar)							\
338     : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4),		\
339       "r" (_a5)								\
340     : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
341     (long int) resultvar;						\
342 })
343 
344 #undef internal_syscall6
345 #define internal_syscall6(number, arg1, arg2, arg3, arg4, arg5, arg6) \
346 ({									\
347     unsigned long int resultvar;					\
348     TYPEFY (arg6, __arg6) = ARGIFY (arg6);			 	\
349     TYPEFY (arg5, __arg5) = ARGIFY (arg5);			 	\
350     TYPEFY (arg4, __arg4) = ARGIFY (arg4);			 	\
351     TYPEFY (arg3, __arg3) = ARGIFY (arg3);			 	\
352     TYPEFY (arg2, __arg2) = ARGIFY (arg2);			 	\
353     TYPEFY (arg1, __arg1) = ARGIFY (arg1);			 	\
354     register TYPEFY (arg6, _a6) asm ("r9") = __arg6;			\
355     register TYPEFY (arg5, _a5) asm ("r8") = __arg5;			\
356     register TYPEFY (arg4, _a4) asm ("r10") = __arg4;			\
357     register TYPEFY (arg3, _a3) asm ("rdx") = __arg3;			\
358     register TYPEFY (arg2, _a2) asm ("rsi") = __arg2;			\
359     register TYPEFY (arg1, _a1) asm ("rdi") = __arg1;			\
360     asm volatile (							\
361     "syscall\n\t"							\
362     : "=a" (resultvar)							\
363     : "0" (number), "r" (_a1), "r" (_a2), "r" (_a3), "r" (_a4),		\
364       "r" (_a5), "r" (_a6)						\
365     : "memory", REGISTERS_CLOBBERED_BY_SYSCALL);			\
366     (long int) resultvar;						\
367 })
368 
369 
370 # define VDSO_NAME  "LINUX_2.6"
371 # define VDSO_HASH  61765110
372 
373 /* List of system calls which are supported as vsyscalls.  */
374 # define HAVE_CLOCK_GETTIME64_VSYSCALL  "__vdso_clock_gettime"
375 # define HAVE_GETTIMEOFDAY_VSYSCALL     "__vdso_gettimeofday"
376 # define HAVE_TIME_VSYSCALL             "__vdso_time"
377 # define HAVE_GETCPU_VSYSCALL		"__vdso_getcpu"
378 # define HAVE_CLOCK_GETRES64_VSYSCALL   "__vdso_clock_getres"
379 
380 # define HAVE_CLONE3_WRAPPER			1
381 
382 #endif	/* __ASSEMBLER__ */
383 
384 
385 /* Pointer mangling support.  */
386 #if IS_IN (rtld)
387 /* We cannot use the thread descriptor because in ld.so we use setjmp
388    earlier than the descriptor is initialized.  */
389 # ifdef __ASSEMBLER__
390 #  define PTR_MANGLE(reg)	xor __pointer_chk_guard_local(%rip), reg;    \
391 				rol $2*LP_SIZE+1, reg
392 #  define PTR_DEMANGLE(reg)	ror $2*LP_SIZE+1, reg;			     \
393 				xor __pointer_chk_guard_local(%rip), reg
394 # else
395 #  define PTR_MANGLE(reg)	asm ("xor __pointer_chk_guard_local(%%rip), %0\n" \
396 				     "rol $2*" LP_SIZE "+1, %0"			  \
397 				     : "=r" (reg) : "0" (reg))
398 #  define PTR_DEMANGLE(reg)	asm ("ror $2*" LP_SIZE "+1, %0\n"		  \
399 				     "xor __pointer_chk_guard_local(%%rip), %0"   \
400 				     : "=r" (reg) : "0" (reg))
401 # endif
402 #else
403 # ifdef __ASSEMBLER__
404 #  define PTR_MANGLE(reg)	xor %fs:POINTER_GUARD, reg;		      \
405 				rol $2*LP_SIZE+1, reg
406 #  define PTR_DEMANGLE(reg)	ror $2*LP_SIZE+1, reg;			      \
407 				xor %fs:POINTER_GUARD, reg
408 # else
409 #  define PTR_MANGLE(var)	asm ("xor %%fs:%c2, %0\n"		      \
410 				     "rol $2*" LP_SIZE "+1, %0"		      \
411 				     : "=r" (var)			      \
412 				     : "0" (var),			      \
413 				       "i" (offsetof (tcbhead_t,	      \
414 						      pointer_guard)))
415 #  define PTR_DEMANGLE(var)	asm ("ror $2*" LP_SIZE "+1, %0\n"	      \
416 				     "xor %%fs:%c2, %0"			      \
417 				     : "=r" (var)			      \
418 				     : "0" (var),			      \
419 				       "i" (offsetof (tcbhead_t,	      \
420 						      pointer_guard)))
421 # endif
422 #endif
423 
424 /* How to pass the off{64}_t argument on p{readv,writev}{64}.  */
425 #undef LO_HI_LONG
426 #define LO_HI_LONG(val) (val), 0
427 
428 /* Each shadow stack slot takes 8 bytes.  Assuming that each stack
429    frame takes 256 bytes, this is used to compute shadow stack size
430    from stack size.  */
431 #define STACK_SIZE_TO_SHADOW_STACK_SIZE_SHIFT 5
432 
433 #endif /* linux/x86_64/sysdep.h */
434