1 /* Copyright (C) 2001-2005, 2007 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 <http://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 <sys/syscall.h> 23 #include <common/sysdep.h> 24 25 #ifdef __ASSEMBLER__ 26 27 /* Syntactic details of assembler. */ 28 29 /* ELF uses byte-counts for .align, most others use log2 of count of bytes. */ 30 #define ALIGNARG(log2) 1<<log2 31 /* For ELF we need the `.type' directive to make shared libs work right. */ 32 #define ASM_TYPE_DIRECTIVE(name,typearg) .type name,typearg; 33 #define ASM_SIZE_DIRECTIVE(name) .size name,.-name; 34 35 /* In ELF C symbols are asm symbols. */ 36 #undef NO_UNDERSCORES 37 #define NO_UNDERSCORES 38 39 /* Define an entry point visible from C. */ 40 #define ENTRY(name) \ 41 .globl C_SYMBOL_NAME(name); \ 42 ASM_TYPE_DIRECTIVE (C_SYMBOL_NAME(name),@function) \ 43 .align ALIGNARG(4); \ 44 C_LABEL(name) \ 45 cfi_startproc; 46 47 #undef END 48 #define END(name) \ 49 cfi_endproc; \ 50 ASM_SIZE_DIRECTIVE(name) 51 52 #ifdef NO_UNDERSCORES 53 /* Since C identifiers are not normally prefixed with an underscore 54 on this system, the asm identifier `syscall_error' intrudes on the 55 C name space. Make sure we use an innocuous name. */ 56 #define syscall_error __syscall_error 57 #define mcount _mcount 58 #endif 59 60 #define PSEUDO(name, syscall_name, args) \ 61 lose: \ 62 jmp JUMPTARGET(syscall_error) \ 63 .globl syscall_error; \ 64 ENTRY (name) \ 65 DO_CALL (syscall_name, args); \ 66 jb lose 67 68 #undef PSEUDO_END 69 #define PSEUDO_END(name) \ 70 END (name) 71 72 #undef JUMPTARGET 73 #ifdef __PIC__ 74 #define JUMPTARGET(name) name##@PLT 75 #else 76 #define JUMPTARGET(name) name 77 #endif 78 79 /* Local label name for asm code. */ 80 #ifndef L 81 #define L(name) .L##name 82 #endif 83 84 #endif /* __ASSEMBLER__ */ 85 86 /* For Linux we can use the system call table in the header file 87 /usr/include/asm/unistd.h 88 of the kernel. But these symbols do not follow the SYS_* syntax 89 so we have to redefine the `SYS_ify' macro here. */ 90 #undef SYS_ify 91 #define SYS_ify(syscall_name) __NR_##syscall_name 92 93 /* This is a kludge to make syscalls.list find these under the names 94 pread and pwrite, since some kernel headers define those names 95 and some define the *64 names for the same system calls. */ 96 #if !defined __NR_pread && defined __NR_pread64 97 # define __NR_pread __NR_pread64 98 #endif 99 #if !defined __NR_pwrite && defined __NR_pwrite64 100 # define __NR_pwrite __NR_pwrite64 101 #endif 102 103 /* This is to help the old kernel headers where __NR_semtimedop is not 104 available. */ 105 #ifndef __NR_semtimedop 106 # define __NR_semtimedop 220 107 #endif 108 109 110 #ifdef __ASSEMBLER__ 111 112 /* Linux uses a negative return value to indicate syscall errors, 113 unlike most Unices, which use the condition codes' carry flag. 114 115 Since version 2.1 the return value of a system call might be 116 negative even if the call succeeded. E.g., the `lseek' system call 117 might return a large offset. Therefore we must not anymore test 118 for < 0, but test for a real error by making sure the value in %eax 119 is a real error number. Linus said he will make sure the no syscall 120 returns a value in -1 .. -4095 as a valid result so we can savely 121 test with -4095. */ 122 123 /* We don't want the label for the error handle to be global when we define 124 it here. */ 125 # ifdef __PIC__ 126 # define SYSCALL_ERROR_LABEL 0f 127 # else 128 # define SYSCALL_ERROR_LABEL syscall_error 129 # endif 130 131 # undef PSEUDO 132 # define PSEUDO(name, syscall_name, args) \ 133 .text; \ 134 ENTRY (name) \ 135 DO_CALL (syscall_name, args); \ 136 cmpq $-4095, %rax; \ 137 jae SYSCALL_ERROR_LABEL; \ 138 L(pseudo_end): 139 140 # undef PSEUDO_END 141 # define PSEUDO_END(name) \ 142 SYSCALL_ERROR_HANDLER \ 143 END (name) 144 145 # undef PSEUDO_NOERRNO 146 # define PSEUDO_NOERRNO(name, syscall_name, args) \ 147 .text; \ 148 ENTRY (name) \ 149 DO_CALL (syscall_name, args) 150 151 # undef PSEUDO_END_NOERRNO 152 # define PSEUDO_END_NOERRNO(name) \ 153 END (name) 154 155 # define ret_NOERRNO ret 156 157 # undef PSEUDO_ERRVAL 158 # define PSEUDO_ERRVAL(name, syscall_name, args) \ 159 .text; \ 160 ENTRY (name) \ 161 DO_CALL (syscall_name, args); \ 162 negq %rax 163 164 # undef PSEUDO_END_ERRVAL 165 # define PSEUDO_END_ERRVAL(name) \ 166 END (name) 167 168 # ifndef __PIC__ 169 # define SYSCALL_ERROR_HANDLER /* Nothing here; code in sysdep.S is used. */ 170 # elif USE___THREAD 171 # define SYSCALL_ERROR_ERRNO errno 172 # define SYSCALL_ERROR_HANDLER \ 173 0: \ 174 movq SYSCALL_ERROR_ERRNO@GOTTPOFF(%rip), %rcx;\ 175 xorl %edx, %edx; \ 176 subq %rax, %rdx; \ 177 movl %edx, %fs:(%rcx); \ 178 orq $-1, %rax; \ 179 jmp L(pseudo_end); 180 # elif defined _LIBC_REENTRANT 181 /* Store (- %rax) into errno through the GOT. 182 Note that errno occupies only 4 bytes. */ 183 # define SYSCALL_ERROR_HANDLER \ 184 0: \ 185 xorl %edx, %edx; \ 186 subq %rax, %rdx; \ 187 pushq %rdx; \ 188 cfi_adjust_cfa_offset(8); \ 189 call __errno_location@PLT; \ 190 popq %rdx; \ 191 cfi_adjust_cfa_offset(-8); \ 192 movl %edx, (%rax); \ 193 orq $-1, %rax; \ 194 jmp L(pseudo_end); 195 196 /* A quick note: it is assumed that the call to `__errno_location' does 197 not modify the stack! */ 198 # else /* Not _LIBC_REENTRANT. */ 199 # define SYSCALL_ERROR_HANDLER \ 200 0:movq errno@GOTPCREL(%RIP), %rcx; \ 201 xorl %edx, %edx; \ 202 subq %rax, %rdx; \ 203 movl %edx, (%rcx); \ 204 orq $-1, %rax; \ 205 jmp L(pseudo_end); 206 # endif /* __PIC__ */ 207 208 /* The Linux/x86-64 kernel expects the system call parameters in 209 registers according to the following table: 210 211 syscall number rax 212 arg 1 rdi 213 arg 2 rsi 214 arg 3 rdx 215 arg 4 r10 216 arg 5 r8 217 arg 6 r9 218 219 The Linux kernel uses and destroys internally these registers: 220 return address from 221 syscall rcx 222 eflags from syscall r11 223 224 Normal function call, including calls to the system call stub 225 functions in the libc, get the first six parameters passed in 226 registers and the seventh parameter and later on the stack. The 227 register use is as follows: 228 229 system call number in the DO_CALL macro 230 arg 1 rdi 231 arg 2 rsi 232 arg 3 rdx 233 arg 4 rcx 234 arg 5 r8 235 arg 6 r9 236 237 We have to take care that the stack is aligned to 16 bytes. When 238 called the stack is not aligned since the return address has just 239 been pushed. 240 241 242 Syscalls of more than 6 arguments are not supported. */ 243 244 # undef DO_CALL 245 # define DO_CALL(syscall_name, args) \ 246 DOARGS_##args \ 247 movl $SYS_ify (syscall_name), %eax; \ 248 syscall; 249 250 # define DOARGS_0 /* nothing */ 251 # define DOARGS_1 /* nothing */ 252 # define DOARGS_2 /* nothing */ 253 # define DOARGS_3 /* nothing */ 254 # define DOARGS_4 movq %rcx, %r10; 255 # define DOARGS_5 DOARGS_4 256 # define DOARGS_6 DOARGS_5 257 258 #endif /* __ASSEMBLER__ */ 259 #endif /* linux/x86_64/sysdep.h */ 260