Back to index

glibc  2.9
sysdep.h
Go to the documentation of this file.
00001 /* Copyright (C) 2001-2005, 2007 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003 
00004    The GNU C Library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Lesser General Public
00006    License as published by the Free Software Foundation; either
00007    version 2.1 of the License, or (at your option) any later version.
00008 
00009    The GNU C Library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Lesser General Public License for more details.
00013 
00014    You should have received a copy of the GNU Lesser General Public
00015    License along with the GNU C Library; if not, write to the Free
00016    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00017    02111-1307 USA.  */
00018 
00019 #ifndef _LINUX_X86_64_SYSDEP_H
00020 #define _LINUX_X86_64_SYSDEP_H 1
00021 
00022 /* There is some commonality.  */
00023 #include <sysdeps/unix/x86_64/sysdep.h>
00024 #include <bp-sym.h>
00025 #include <bp-asm.h>
00026 #include <tls.h>
00027 
00028 #ifdef IS_IN_rtld
00029 # include <dl-sysdep.h>            /* Defines RTLD_PRIVATE_ERRNO.  */
00030 #endif
00031 
00032 /* For Linux we can use the system call table in the header file
00033        /usr/include/asm/unistd.h
00034    of the kernel.  But these symbols do not follow the SYS_* syntax
00035    so we have to redefine the `SYS_ify' macro here.  */
00036 #undef SYS_ify
00037 #define SYS_ify(syscall_name)      __NR_##syscall_name
00038 
00039 /* This is a kludge to make syscalls.list find these under the names
00040    pread and pwrite, since some kernel headers define those names
00041    and some define the *64 names for the same system calls.  */
00042 #if !defined __NR_pread && defined __NR_pread64
00043 # define __NR_pread __NR_pread64
00044 #endif
00045 #if !defined __NR_pwrite && defined __NR_pwrite64
00046 # define __NR_pwrite __NR_pwrite64
00047 #endif
00048 
00049 /* This is to help the old kernel headers where __NR_semtimedop is not
00050    available.  */
00051 #ifndef __NR_semtimedop
00052 # define __NR_semtimedop 220
00053 #endif
00054 
00055 
00056 #ifdef __ASSEMBLER__
00057 
00058 /* Linux uses a negative return value to indicate syscall errors,
00059    unlike most Unices, which use the condition codes' carry flag.
00060 
00061    Since version 2.1 the return value of a system call might be
00062    negative even if the call succeeded.    E.g., the `lseek' system call
00063    might return a large offset.     Therefore we must not anymore test
00064    for < 0, but test for a real error by making sure the value in %eax
00065    is a real error number.  Linus said he will make sure the no syscall
00066    returns a value in -1 .. -4095 as a valid result so we can savely
00067    test with -4095.  */
00068 
00069 /* We don't want the label for the error handle to be global when we define
00070    it here.  */
00071 # ifdef PIC
00072 #  define SYSCALL_ERROR_LABEL 0f
00073 # else
00074 #  define SYSCALL_ERROR_LABEL syscall_error
00075 # endif
00076 
00077 # undef       PSEUDO
00078 # define PSEUDO(name, syscall_name, args)                            \
00079   .text;                                                             \
00080   ENTRY (name)                                                              \
00081     DO_CALL (syscall_name, args);                                    \
00082     cmpq $-4095, %rax;                                                      \
00083     jae SYSCALL_ERROR_LABEL;                                                \
00084   L(pseudo_end):
00085 
00086 # undef       PSEUDO_END
00087 # define PSEUDO_END(name)                                            \
00088   SYSCALL_ERROR_HANDLER                                                     \
00089   END (name)
00090 
00091 # undef       PSEUDO_NOERRNO
00092 # define PSEUDO_NOERRNO(name, syscall_name, args) \
00093   .text;                                                             \
00094   ENTRY (name)                                                              \
00095     DO_CALL (syscall_name, args)
00096 
00097 # undef       PSEUDO_END_NOERRNO
00098 # define PSEUDO_END_NOERRNO(name) \
00099   END (name)
00100 
00101 # define ret_NOERRNO ret
00102 
00103 # undef       PSEUDO_ERRVAL
00104 # define PSEUDO_ERRVAL(name, syscall_name, args) \
00105   .text;                                                             \
00106   ENTRY (name)                                                              \
00107     DO_CALL (syscall_name, args);                                    \
00108     negq %rax
00109 
00110 # undef       PSEUDO_END_ERRVAL
00111 # define PSEUDO_END_ERRVAL(name) \
00112   END (name)
00113 
00114 # define ret_ERRVAL ret
00115 
00116 # ifndef PIC
00117 #  define SYSCALL_ERROR_HANDLER    /* Nothing here; code in sysdep.S is used.  */
00118 # elif RTLD_PRIVATE_ERRNO
00119 #  define SYSCALL_ERROR_HANDLER                  \
00120 0:                                        \
00121   leaq rtld_errno(%rip), %rcx;                   \
00122   xorl %edx, %edx;                        \
00123   subq %rax, %rdx;                        \
00124   movl %edx, (%rcx);                      \
00125   orq $-1, %rax;                          \
00126   jmp L(pseudo_end);
00127 # elif USE___THREAD
00128 #  ifndef NOT_IN_libc
00129 #   define SYSCALL_ERROR_ERRNO __libc_errno
00130 #  else
00131 #   define SYSCALL_ERROR_ERRNO errno
00132 #  endif
00133 #  define SYSCALL_ERROR_HANDLER                  \
00134 0:                                        \
00135   movq SYSCALL_ERROR_ERRNO@GOTTPOFF(%rip), %rcx;\
00136   xorl %edx, %edx;                        \
00137   subq %rax, %rdx;                        \
00138   movl %edx, %fs:(%rcx);                  \
00139   orq $-1, %rax;                          \
00140   jmp L(pseudo_end);
00141 # elif defined _LIBC_REENTRANT
00142 /* Store (- %rax) into errno through the GOT.
00143    Note that errno occupies only 4 bytes.  */
00144 #  define SYSCALL_ERROR_HANDLER                  \
00145 0:                                        \
00146   xorl %edx, %edx;                        \
00147   subq %rax, %rdx;                        \
00148   pushq %rdx;                             \
00149   cfi_adjust_cfa_offset(8);               \
00150   PUSH_ERRNO_LOCATION_RETURN;                    \
00151   call BP_SYM (__errno_location)@PLT;            \
00152   POP_ERRNO_LOCATION_RETURN;                     \
00153   popq %rdx;                              \
00154   cfi_adjust_cfa_offset(-8);                     \
00155   movl %edx, (%rax);                      \
00156   orq $-1, %rax;                          \
00157   jmp L(pseudo_end);
00158 
00159 /* A quick note: it is assumed that the call to `__errno_location' does
00160    not modify the stack!  */
00161 # else /* Not _LIBC_REENTRANT.  */
00162 #  define SYSCALL_ERROR_HANDLER                  \
00163 0:movq errno@GOTPCREL(%RIP), %rcx;        \
00164   xorl %edx, %edx;                        \
00165   subq %rax, %rdx;                        \
00166   movl %edx, (%rcx);                      \
00167   orq $-1, %rax;                          \
00168   jmp L(pseudo_end);
00169 # endif       /* PIC */
00170 
00171 /* The Linux/x86-64 kernel expects the system call parameters in
00172    registers according to the following table:
00173 
00174     syscall number   rax
00175     arg 1            rdi
00176     arg 2            rsi
00177     arg 3            rdx
00178     arg 4            r10
00179     arg 5            r8
00180     arg 6            r9
00181 
00182     The Linux kernel uses and destroys internally these registers:
00183     return address from
00184     syscall          rcx
00185     eflags from syscall     r11
00186 
00187     Normal function call, including calls to the system call stub
00188     functions in the libc, get the first six parameters passed in
00189     registers and the seventh parameter and later on the stack.  The
00190     register use is as follows:
00191 
00192      system call number     in the DO_CALL macro
00193      arg 1           rdi
00194      arg 2           rsi
00195      arg 3           rdx
00196      arg 4           rcx
00197      arg 5           r8
00198      arg 6           r9
00199 
00200     We have to take care that the stack is aligned to 16 bytes.  When
00201     called the stack is not aligned since the return address has just
00202     been pushed.
00203 
00204 
00205     Syscalls of more than 6 arguments are not supported.  */
00206 
00207 # undef       DO_CALL
00208 # define DO_CALL(syscall_name, args)             \
00209     DOARGS_##args                         \
00210     movl $SYS_ify (syscall_name), %eax;          \
00211     syscall;
00212 
00213 # define DOARGS_0 /* nothing */
00214 # define DOARGS_1 /* nothing */
00215 # define DOARGS_2 /* nothing */
00216 # define DOARGS_3 /* nothing */
00217 # define DOARGS_4 movq %rcx, %r10;
00218 # define DOARGS_5 DOARGS_4
00219 # define DOARGS_6 DOARGS_5
00220 
00221 #else  /* !__ASSEMBLER__ */
00222 /* Define a macro which expands inline into the wrapper code for a system
00223    call.  */
00224 # undef INLINE_SYSCALL
00225 # define INLINE_SYSCALL(name, nr, args...) \
00226   ({                                                                 \
00227     unsigned long int resultvar = INTERNAL_SYSCALL (name, , nr, args);             \
00228     if (__builtin_expect (INTERNAL_SYSCALL_ERROR_P (resultvar, ), 0))       \
00229       {                                                                     \
00230        __set_errno (INTERNAL_SYSCALL_ERRNO (resultvar, ));                  \
00231        resultvar = (unsigned long int) -1;                                  \
00232       }                                                                     \
00233     (long int) resultvar; })
00234 
00235 # undef INTERNAL_SYSCALL_DECL
00236 # define INTERNAL_SYSCALL_DECL(err) do { } while (0)
00237 
00238 # define INTERNAL_SYSCALL_NCS(name, err, nr, args...) \
00239   ({                                                                 \
00240     unsigned long int resultvar;                                     \
00241     LOAD_ARGS_##nr (args)                                            \
00242     LOAD_REGS_##nr                                                   \
00243     asm volatile (                                                   \
00244     "syscall\n\t"                                                    \
00245     : "=a" (resultvar)                                                      \
00246     : "0" (name) ASM_ARGS_##nr : "memory", "cc", "r11", "cx");              \
00247     (long int) resultvar; })
00248 # undef INTERNAL_SYSCALL
00249 # define INTERNAL_SYSCALL(name, err, nr, args...) \
00250   INTERNAL_SYSCALL_NCS (__NR_##name, err, nr, ##args)
00251 
00252 # undef INTERNAL_SYSCALL_ERROR_P
00253 # define INTERNAL_SYSCALL_ERROR_P(val, err) \
00254   ((unsigned long int) (long int) (val) >= -4095L)
00255 
00256 # undef INTERNAL_SYSCALL_ERRNO
00257 # define INTERNAL_SYSCALL_ERRNO(val, err) (-(val))
00258 
00259 # ifdef SHARED
00260 #  define INLINE_VSYSCALL(name, nr, args...) \
00261   ({                                                                 \
00262     __label__ out;                                                   \
00263     __label__ iserr;                                                 \
00264     INTERNAL_SYSCALL_DECL (sc_err);                                         \
00265     long int sc_ret;                                                 \
00266                                                                      \
00267     __typeof (__vdso_##name) vdsop = __vdso_##name;                         \
00268     PTR_DEMANGLE (vdsop);                                            \
00269     if (vdsop != NULL)                                                      \
00270       {                                                                     \
00271        sc_ret = vdsop (args);                                               \
00272        if (!INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err))                      \
00273          goto out;                                                   \
00274        if (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err) != ENOSYS)               \
00275          goto iserr;                                                 \
00276       }                                                                     \
00277                                                                      \
00278     sc_ret = INTERNAL_SYSCALL (name, sc_err, nr, ##args);                   \
00279     if (INTERNAL_SYSCALL_ERROR_P (sc_ret, sc_err))                          \
00280       {                                                                     \
00281       iserr:                                                         \
00282         __set_errno (INTERNAL_SYSCALL_ERRNO (sc_ret, sc_err));              \
00283         sc_ret = -1L;                                                       \
00284       }                                                                     \
00285   out:                                                               \
00286     sc_ret;                                                          \
00287   })
00288 #  define INTERNAL_VSYSCALL(name, err, nr, args...) \
00289   ({                                                                 \
00290     __label__ out;                                                   \
00291     long int v_ret;                                                  \
00292                                                                      \
00293     __typeof (__vdso_##name) vdsop = __vdso_##name;                         \
00294     PTR_DEMANGLE (vdsop);                                            \
00295     if (vdsop != NULL)                                                      \
00296       {                                                                     \
00297        v_ret = vdsop (args);                                                \
00298        if (!INTERNAL_SYSCALL_ERROR_P (v_ret, err)                           \
00299            || INTERNAL_SYSCALL_ERRNO (v_ret, err) != ENOSYS)                \
00300          goto out;                                                   \
00301       }                                                                     \
00302     v_ret = INTERNAL_SYSCALL (name, err, nr, ##args);                       \
00303   out:                                                               \
00304     v_ret;                                                           \
00305   })
00306 
00307 /* List of system calls which are supported as vsyscalls.  */
00308 #  define HAVE_CLOCK_GETTIME_VSYSCALL     1
00309 
00310 # else
00311 #  define INLINE_VSYSCALL(name, nr, args...) \
00312   INLINE_SYSCALL (name, nr, ##args)
00313 #  define INTERNAL_VSYSCALL(name, err, nr, args...) \
00314   INTERNAL_SYSCALL (name, err, nr, ##args)
00315 # endif
00316 
00317 # define LOAD_ARGS_0()
00318 # define LOAD_REGS_0
00319 # define ASM_ARGS_0
00320 
00321 # define LOAD_ARGS_1(a1)                         \
00322   long int __arg1 = (long int) (a1);                    \
00323   LOAD_ARGS_0 ()
00324 # define LOAD_REGS_1                             \
00325   register long int _a1 asm ("rdi") = __arg1;           \
00326   LOAD_REGS_0
00327 # define ASM_ARGS_1  ASM_ARGS_0, "r" (_a1)
00328 
00329 # define LOAD_ARGS_2(a1, a2)                            \
00330   long int __arg2 = (long int) (a2);                    \
00331   LOAD_ARGS_1 (a1)
00332 # define LOAD_REGS_2                             \
00333   register long int _a2 asm ("rsi") = __arg2;           \
00334   LOAD_REGS_1
00335 # define ASM_ARGS_2  ASM_ARGS_1, "r" (_a2)
00336 
00337 # define LOAD_ARGS_3(a1, a2, a3)                 \
00338   long int __arg3 = (long int) (a3);                    \
00339   LOAD_ARGS_2 (a1, a2)
00340 # define LOAD_REGS_3                             \
00341   register long int _a3 asm ("rdx") = __arg3;           \
00342   LOAD_REGS_2
00343 # define ASM_ARGS_3  ASM_ARGS_2, "r" (_a3)
00344 
00345 # define LOAD_ARGS_4(a1, a2, a3, a4)                    \
00346   long int __arg4 = (long int) (a4);                    \
00347   LOAD_ARGS_3 (a1, a2, a3)
00348 # define LOAD_REGS_4                             \
00349   register long int _a4 asm ("r10") = __arg4;           \
00350   LOAD_REGS_3
00351 # define ASM_ARGS_4  ASM_ARGS_3, "r" (_a4)
00352 
00353 # define LOAD_ARGS_5(a1, a2, a3, a4, a5)         \
00354   long int __arg5 = (long int) (a5);                    \
00355   LOAD_ARGS_4 (a1, a2, a3, a4)
00356 # define LOAD_REGS_5                             \
00357   register long int _a5 asm ("r8") = __arg5;            \
00358   LOAD_REGS_4
00359 # define ASM_ARGS_5  ASM_ARGS_4, "r" (_a5)
00360 
00361 # define LOAD_ARGS_6(a1, a2, a3, a4, a5, a6)            \
00362   long int __arg6 = (long int) (a6);                    \
00363   LOAD_ARGS_5 (a1, a2, a3, a4, a5)
00364 # define LOAD_REGS_6                             \
00365   register long int _a6 asm ("r9") = __arg6;            \
00366   LOAD_REGS_5
00367 # define ASM_ARGS_6  ASM_ARGS_5, "r" (_a6)
00368 
00369 #endif /* __ASSEMBLER__ */
00370 
00371 
00372 /* Pointer mangling support.  */
00373 #if defined NOT_IN_libc && defined IS_IN_rtld
00374 /* We cannot use the thread descriptor because in ld.so we use setjmp
00375    earlier than the descriptor is initialized.  */
00376 # ifdef __ASSEMBLER__
00377 #  define PTR_MANGLE(reg)   xorq __pointer_chk_guard_local(%rip), reg;    \
00378                             rolq $17, reg
00379 #  define PTR_DEMANGLE(reg) rorq $17, reg;                                  \
00380                             xorq __pointer_chk_guard_local(%rip), reg
00381 # else
00382 #  define PTR_MANGLE(reg)   asm ("xorq __pointer_chk_guard_local(%%rip), %0\n" \
00383                                  "rolq $17, %0"                      \
00384                                  : "=r" (reg) : "0" (reg))
00385 #  define PTR_DEMANGLE(reg) asm ("rorq $17, %0\n"                           \
00386                                  "xorq __pointer_chk_guard_local(%%rip), %0" \
00387                                  : "=r" (reg) : "0" (reg))
00388 # endif
00389 #else
00390 # ifdef __ASSEMBLER__
00391 #  define PTR_MANGLE(reg)   xorq %fs:POINTER_GUARD, reg;                    \
00392                             rolq $17, reg
00393 #  define PTR_DEMANGLE(reg) rorq $17, reg;                                  \
00394                             xorq %fs:POINTER_GUARD, reg
00395 # else
00396 #  define PTR_MANGLE(var)   asm ("xorq %%fs:%c2, %0\n"               \
00397                                  "rolq $17, %0"                      \
00398                                  : "=r" (var)                        \
00399                                  : "0" (var),                        \
00400                                    "i" (offsetof (tcbhead_t,         \
00401                                                 pointer_guard)))
00402 #  define PTR_DEMANGLE(var) asm ("rorq $17, %0\n"                           \
00403                                  "xorq %%fs:%c2, %0"                 \
00404                                  : "=r" (var)                        \
00405                                  : "0" (var),                        \
00406                                    "i" (offsetof (tcbhead_t,         \
00407                                                 pointer_guard)))
00408 # endif
00409 #endif
00410 
00411 #endif /* linux/x86_64/sysdep.h */