Back to index

glibc  2.9
sysdep.h
Go to the documentation of this file.
00001 /* Copyright (C) 1992, 1995, 1996, 2000, 2003, 2004, 2006
00002    Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Contributed by Brendan Kehoe (brendan@zen.org).
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #include <sysdeps/unix/sysdep.h>
00022 
00023 #ifdef __ASSEMBLER__
00024 
00025 #ifdef __linux__
00026 # include <alpha/regdef.h>
00027 #else
00028 # include <regdef.h>
00029 #endif
00030 
00031 #include <tls.h>            /* Defines USE___THREAD.  */
00032 
00033 #ifdef IS_IN_rtld
00034 # include <dl-sysdep.h>         /* Defines RTLD_PRIVATE_ERRNO.  */
00035 #endif
00036 
00037 
00038 #ifdef __STDC__
00039 #define __LABEL(x)   x##:
00040 #else
00041 #define __LABEL(x)   x:
00042 #endif
00043 
00044 #define LEAF(name, framesize)                    \
00045   .globl name;                                   \
00046   .align 4;                               \
00047   .ent name, 0;                                  \
00048   __LABEL(name)                                  \
00049   .frame sp, framesize, ra
00050 
00051 #define ENTRY(name)                       \
00052   .globl name;                                   \
00053   .align 4;                               \
00054   .ent name, 0;                                  \
00055   __LABEL(name)                                  \
00056   .frame sp, 0, ra
00057 
00058 /* Mark the end of function SYM.  */
00059 #undef END
00060 #define END(sym)     .end sym
00061 
00062 #ifdef PROF
00063 # define PSEUDO_PROLOGUE                  \
00064        .frame sp, 0, ra;                  \
00065        ldgp   gp,0(pv);                   \
00066        .set noat;                         \
00067        lda    AT,_mcount;                 \
00068        jsr    AT,(AT),_mcount;            \
00069        .set at;                           \
00070        .prologue 1
00071 #elif defined PIC
00072 # define PSEUDO_PROLOGUE                  \
00073        .frame sp, 0, ra;                  \
00074        .prologue 0
00075 #else
00076 # define PSEUDO_PROLOGUE                  \
00077        .frame sp, 0, ra;                  \
00078        ldgp   gp,0(pv);                   \
00079        .prologue 1
00080 #endif /* PROF */
00081 
00082 #if RTLD_PRIVATE_ERRNO
00083 # define SYSCALL_ERROR_LABEL       $syscall_error
00084 # define SYSCALL_ERROR_HANDLER                   \
00085        stl    v0, rtld_errno(gp)   !gprel;       \
00086        lda    v0, -1;                            \
00087        ret
00088 #elif defined(PIC)
00089 # define SYSCALL_ERROR_LABEL       __syscall_error
00090 # define SYSCALL_ERROR_HANDLER \
00091        br     $31, __syscall_error !samegp
00092 #else
00093 # define SYSCALL_ERROR_LABEL       $syscall_error
00094 # define SYSCALL_ERROR_HANDLER \
00095        jmp    $31, __syscall_error
00096 #endif /* RTLD_PRIVATE_ERRNO */
00097 
00098 /* Overridden by specific syscalls.  */
00099 #undef PSEUDO_PREPARE_ARGS
00100 #define PSEUDO_PREPARE_ARGS /* Nothing.  */
00101 
00102 #define PSEUDO(name, syscall_name, args)  \
00103        .globl name;                       \
00104        .align 4;                          \
00105        .ent name,0;                       \
00106 __LABEL(name)                             \
00107        PSEUDO_PROLOGUE;                   \
00108        PSEUDO_PREPARE_ARGS                \
00109        lda    v0, SYS_ify(syscall_name);  \
00110        call_pal PAL_callsys;                     \
00111        bne    a3, SYSCALL_ERROR_LABEL
00112 
00113 #undef PSEUDO_END
00114 #if defined(PIC) && !RTLD_PRIVATE_ERRNO
00115 # define PSEUDO_END(sym)  END(sym)
00116 #else
00117 # define PSEUDO_END(sym)                  \
00118 $syscall_error:                                  \
00119        SYSCALL_ERROR_HANDLER;                    \
00120        END(sym)
00121 #endif
00122 
00123 #define PSEUDO_NOERRNO(name, syscall_name, args) \
00124        .globl name;                              \
00125        .align 4;                                 \
00126        .ent name,0;                              \
00127 __LABEL(name)                                    \
00128        PSEUDO_PROLOGUE;                          \
00129        PSEUDO_PREPARE_ARGS                       \
00130        lda    v0, SYS_ify(syscall_name);         \
00131        call_pal PAL_callsys;
00132 
00133 #undef PSEUDO_END_NOERRNO
00134 #define PSEUDO_END_NOERRNO(sym)  END(sym)
00135 
00136 #define ret_NOERRNO ret
00137 
00138 #define PSEUDO_ERRVAL(name, syscall_name, args)  \
00139        .globl name;                              \
00140        .align 4;                                 \
00141        .ent name,0;                              \
00142 __LABEL(name)                                    \
00143        PSEUDO_PROLOGUE;                          \
00144        PSEUDO_PREPARE_ARGS                       \
00145        lda    v0, SYS_ify(syscall_name);         \
00146        call_pal PAL_callsys;
00147 
00148 #undef PSEUDO_END_ERRVAL
00149 #define PSEUDO_END_ERRVAL(sym)  END(sym)
00150 
00151 #define ret_ERRVAL ret
00152 
00153 #define r0    v0
00154 #define r1    a4
00155 
00156 #define MOVE(x,y)    mov x,y
00157 
00158 #else /* !ASSEMBLER */
00159 
00160 /* ??? Linux needs to be able to override INLINE_SYSCALL for one
00161    particular special case.  Make this easy.  */
00162 
00163 #undef INLINE_SYSCALL
00164 #define INLINE_SYSCALL(name, nr, args...) \
00165        INLINE_SYSCALL1(name, nr, args)
00166 
00167 #define INLINE_SYSCALL1(name, nr, args...)       \
00168 ({                                        \
00169        long _sc_ret, _sc_err;                    \
00170        inline_syscall##nr(__NR_##name, args);    \
00171        if (__builtin_expect (_sc_err, 0)) \
00172          {                                \
00173            __set_errno (_sc_ret);         \
00174            _sc_ret = -1L;                 \
00175          }                                \
00176        _sc_ret;                           \
00177 })
00178 
00179 #define INTERNAL_SYSCALL(name, err_out, nr, args...) \
00180        INTERNAL_SYSCALL1(name, err_out, nr, args)
00181 
00182 #define INTERNAL_SYSCALL1(name, err_out, nr, args...)   \
00183        INTERNAL_SYSCALL_NCS(__NR_##name, err_out, nr, args)
00184 
00185 #define INTERNAL_SYSCALL_NCS(name, err_out, nr, args...) \
00186 ({                                               \
00187        long _sc_ret, _sc_err;                           \
00188        inline_syscall##nr(name, args);                  \
00189        err_out = _sc_err;                        \
00190        _sc_ret;                                  \
00191 })
00192 
00193 #define INTERNAL_SYSCALL_DECL(err)        long int err
00194 #define INTERNAL_SYSCALL_ERROR_P(val, err)       err
00195 #define INTERNAL_SYSCALL_ERRNO(val, err)  val
00196 
00197 #define inline_syscall_clobbers                         \
00198        "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8",  \
00199        "$22", "$23", "$24", "$25", "$27", "$28", "memory"
00200 
00201 /* If TLS is in use, we have a conflict between the PAL_rduniq primitive,
00202    as modeled within GCC, and explicit use of the R0 register.  If we use
00203    the register via the asm, the scheduler may place the PAL_rduniq insn
00204    before we've copied the data from R0 into _sc_ret.  If this happens
00205    we'll get a reload abort, since R0 is live at the same time it is
00206    needed for the PAL_rduniq.
00207 
00208    Solve this by using the "v" constraint instead of an asm for the syscall
00209    output.  We don't do this unconditionally to allow compilation with
00210    older compilers.  */
00211 
00212 #ifdef HAVE___THREAD
00213 #define inline_syscall_r0_asm
00214 #define inline_syscall_r0_out_constraint  "=v"
00215 #else
00216 #define inline_syscall_r0_asm                    __asm__("$0")
00217 #define inline_syscall_r0_out_constraint  "=r"
00218 #endif
00219 
00220 /* It is moderately important optimization-wise to limit the lifetime
00221    of the hard-register variables as much as possible.  Thus we copy
00222    in/out as close to the asm as possible.  */
00223 
00224 #define inline_syscall0(name, args...)                         \
00225 {                                                       \
00226        register long _sc_0 inline_syscall_r0_asm;              \
00227        register long _sc_19 __asm__("$19");                    \
00228                                                         \
00229        _sc_0 = name;                                    \
00230        __asm__ __volatile__                             \
00231          ("callsys # %0 %1 <= %2"                       \
00232           : inline_syscall_r0_out_constraint (_sc_0),          \
00233             "=r"(_sc_19)                                \
00234           : "0"(_sc_0)                                         \
00235           : inline_syscall_clobbers,                           \
00236             "$16", "$17", "$18", "$20", "$21");         \
00237        _sc_ret = _sc_0, _sc_err = _sc_19;               \
00238 }
00239 
00240 #define inline_syscall1(name,arg1)                      \
00241 {                                                       \
00242        register long _sc_0 inline_syscall_r0_asm;              \
00243        register long _sc_16 __asm__("$16");                    \
00244        register long _sc_19 __asm__("$19");                    \
00245        register long _tmp_16 = (long) (arg1);                  \
00246                                                         \
00247        _sc_0 = name;                                    \
00248        _sc_16 = _tmp_16;                                \
00249        __asm__ __volatile__                             \
00250          ("callsys # %0 %1 <= %2 %3"                           \
00251           : inline_syscall_r0_out_constraint (_sc_0),          \
00252             "=r"(_sc_19), "=r"(_sc_16)                         \
00253           : "0"(_sc_0), "2"(_sc_16)                            \
00254           : inline_syscall_clobbers,                           \
00255             "$17", "$18", "$20", "$21");                \
00256        _sc_ret = _sc_0, _sc_err = _sc_19;               \
00257 }
00258 
00259 #define inline_syscall2(name,arg1,arg2)                        \
00260 {                                                       \
00261        register long _sc_0 inline_syscall_r0_asm;              \
00262        register long _sc_16 __asm__("$16");                    \
00263        register long _sc_17 __asm__("$17");                    \
00264        register long _sc_19 __asm__("$19");                    \
00265        register long _tmp_16 = (long) (arg1);                  \
00266        register long _tmp_17 = (long) (arg2);                  \
00267                                                         \
00268        _sc_0 = name;                                    \
00269        _sc_16 = _tmp_16;                                \
00270        _sc_17 = _tmp_17;                                \
00271        __asm__ __volatile__                             \
00272          ("callsys # %0 %1 <= %2 %3 %4"                 \
00273           : inline_syscall_r0_out_constraint (_sc_0),          \
00274             "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17)           \
00275           : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17)        \
00276           : inline_syscall_clobbers,                           \
00277             "$18", "$20", "$21");                       \
00278        _sc_ret = _sc_0, _sc_err = _sc_19;               \
00279 }
00280 
00281 #define inline_syscall3(name,arg1,arg2,arg3)                   \
00282 {                                                       \
00283        register long _sc_0 inline_syscall_r0_asm;              \
00284        register long _sc_16 __asm__("$16");                    \
00285        register long _sc_17 __asm__("$17");                    \
00286        register long _sc_18 __asm__("$18");                    \
00287        register long _sc_19 __asm__("$19");                    \
00288        register long _tmp_16 = (long) (arg1);                  \
00289        register long _tmp_17 = (long) (arg2);                  \
00290        register long _tmp_18 = (long) (arg3);                  \
00291                                                         \
00292        _sc_0 = name;                                    \
00293        _sc_16 = _tmp_16;                                \
00294        _sc_17 = _tmp_17;                                \
00295        _sc_18 = _tmp_18;                                \
00296        __asm__ __volatile__                             \
00297          ("callsys # %0 %1 <= %2 %3 %4 %5"                     \
00298           : inline_syscall_r0_out_constraint (_sc_0),          \
00299             "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17),          \
00300             "=r"(_sc_18)                                \
00301           : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17),              \
00302             "4"(_sc_18)                                 \
00303           : inline_syscall_clobbers, "$20", "$21");            \
00304        _sc_ret = _sc_0, _sc_err = _sc_19;               \
00305 }
00306 
00307 #define inline_syscall4(name,arg1,arg2,arg3,arg4)              \
00308 {                                                       \
00309        register long _sc_0 inline_syscall_r0_asm;              \
00310        register long _sc_16 __asm__("$16");                    \
00311        register long _sc_17 __asm__("$17");                    \
00312        register long _sc_18 __asm__("$18");                    \
00313        register long _sc_19 __asm__("$19");                    \
00314        register long _tmp_16 = (long) (arg1);                  \
00315        register long _tmp_17 = (long) (arg2);                  \
00316        register long _tmp_18 = (long) (arg3);                  \
00317        register long _tmp_19 = (long) (arg4);                  \
00318                                                         \
00319        _sc_0 = name;                                    \
00320        _sc_16 = _tmp_16;                                \
00321        _sc_17 = _tmp_17;                                \
00322        _sc_18 = _tmp_18;                                \
00323        _sc_19 = _tmp_19;                                \
00324        __asm__ __volatile__                             \
00325          ("callsys # %0 %1 <= %2 %3 %4 %5 %6"                  \
00326           : inline_syscall_r0_out_constraint (_sc_0),          \
00327             "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17),          \
00328             "=r"(_sc_18)                                \
00329           : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17),              \
00330             "4"(_sc_18), "1"(_sc_19)                           \
00331           : inline_syscall_clobbers, "$20", "$21");            \
00332        _sc_ret = _sc_0, _sc_err = _sc_19;               \
00333 }
00334 
00335 #define inline_syscall5(name,arg1,arg2,arg3,arg4,arg5)         \
00336 {                                                       \
00337        register long _sc_0 inline_syscall_r0_asm;              \
00338        register long _sc_16 __asm__("$16");                    \
00339        register long _sc_17 __asm__("$17");                    \
00340        register long _sc_18 __asm__("$18");                    \
00341        register long _sc_19 __asm__("$19");                    \
00342        register long _sc_20 __asm__("$20");                    \
00343        register long _tmp_16 = (long) (arg1);                  \
00344        register long _tmp_17 = (long) (arg2);                  \
00345        register long _tmp_18 = (long) (arg3);                  \
00346        register long _tmp_19 = (long) (arg4);                  \
00347        register long _tmp_20 = (long) (arg5);                  \
00348                                                         \
00349        _sc_0 = name;                                    \
00350        _sc_16 = _tmp_16;                                \
00351        _sc_17 = _tmp_17;                                \
00352        _sc_18 = _tmp_18;                                \
00353        _sc_19 = _tmp_19;                                \
00354        _sc_20 = _tmp_20;                                \
00355        __asm__ __volatile__                             \
00356          ("callsys # %0 %1 <= %2 %3 %4 %5 %6 %7"        \
00357           : inline_syscall_r0_out_constraint (_sc_0),          \
00358             "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17),          \
00359             "=r"(_sc_18), "=r"(_sc_20)                         \
00360           : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17),              \
00361             "4"(_sc_18), "1"(_sc_19), "5"(_sc_20)              \
00362           : inline_syscall_clobbers, "$21");                   \
00363        _sc_ret = _sc_0, _sc_err = _sc_19;               \
00364 }
00365 
00366 #define inline_syscall6(name,arg1,arg2,arg3,arg4,arg5,arg6)    \
00367 {                                                       \
00368        register long _sc_0 inline_syscall_r0_asm;              \
00369        register long _sc_16 __asm__("$16");                    \
00370        register long _sc_17 __asm__("$17");                    \
00371        register long _sc_18 __asm__("$18");                    \
00372        register long _sc_19 __asm__("$19");                    \
00373        register long _sc_20 __asm__("$20");                    \
00374        register long _sc_21 __asm__("$21");                    \
00375        register long _tmp_16 = (long) (arg1);                  \
00376        register long _tmp_17 = (long) (arg2);                  \
00377        register long _tmp_18 = (long) (arg3);                  \
00378        register long _tmp_19 = (long) (arg4);                  \
00379        register long _tmp_20 = (long) (arg5);                  \
00380        register long _tmp_21 = (long) (arg6);                  \
00381                                                         \
00382        _sc_0 = name;                                    \
00383        _sc_16 = _tmp_16;                                \
00384        _sc_17 = _tmp_17;                                \
00385        _sc_18 = _tmp_18;                                \
00386        _sc_19 = _tmp_19;                                \
00387        _sc_20 = _tmp_20;                                \
00388        _sc_21 = _tmp_21;                                \
00389        __asm__ __volatile__                             \
00390          ("callsys # %0 %1 <= %2 %3 %4 %5 %6 %7 %8"            \
00391           : inline_syscall_r0_out_constraint (_sc_0),          \
00392             "=r"(_sc_19), "=r"(_sc_16), "=r"(_sc_17),          \
00393             "=r"(_sc_18), "=r"(_sc_20), "=r"(_sc_21)           \
00394           : "0"(_sc_0), "2"(_sc_16), "3"(_sc_17), "4"(_sc_18), \
00395             "1"(_sc_19), "5"(_sc_20), "6"(_sc_21)              \
00396           : inline_syscall_clobbers);                          \
00397        _sc_ret = _sc_0, _sc_err = _sc_19;               \
00398 }
00399 
00400 /* Pointer mangling support.  Note that tls access is slow enough that
00401    we don't deoptimize things by placing the pointer check value there.  */
00402 
00403 #include <stdint.h>
00404 
00405 #if defined NOT_IN_libc && defined IS_IN_rtld
00406 # ifdef __ASSEMBLER__
00407 #  define PTR_MANGLE(dst, src, tmp)                            \
00408        ldah   tmp, __pointer_chk_guard_local($29) !gprelhigh;  \
00409        ldq    tmp, __pointer_chk_guard_local(tmp) !gprellow;   \
00410        xor    src, tmp, dst
00411 #  define PTR_MANGLE2(dst, src, tmp)                           \
00412        xor    src, tmp, dst
00413 #  define PTR_DEMANGLE(dst, tmp)   PTR_MANGLE(dst, dst, tmp)
00414 #  define PTR_DEMANGLE2(dst, tmp)  PTR_MANGLE2(dst, dst, tmp)
00415 # else
00416 extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden;
00417 #  define PTR_MANGLE(var)   \
00418   (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local)
00419 #  define PTR_DEMANGLE(var)  PTR_MANGLE(var)
00420 # endif
00421 #elif defined PIC
00422 # ifdef __ASSEMBLER__
00423 #  define PTR_MANGLE(dst, src, tmp)              \
00424        ldq    tmp, __pointer_chk_guard;   \
00425        xor    src, tmp, dst
00426 #  define PTR_MANGLE2(dst, src, tmp)             \
00427        xor    src, tmp, dst
00428 #  define PTR_DEMANGLE(dst, tmp)   PTR_MANGLE(dst, dst, tmp)
00429 #  define PTR_DEMANGLE2(dst, tmp)  PTR_MANGLE2(dst, dst, tmp)
00430 # else
00431 extern uintptr_t __pointer_chk_guard attribute_relro;
00432 #  define PTR_MANGLE(var)   \
00433        (var) = (void *) ((uintptr_t) (var) ^ __pointer_chk_guard)
00434 #  define PTR_DEMANGLE(var)  PTR_MANGLE(var)
00435 # endif
00436 #endif
00437 
00438 #endif /* ASSEMBLER */