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