Add quite a bit of complication to generate unwind information for
[kopensolaris-gnu/glibc.git] / nptl / sysdeps / unix / sysv / linux / x86_64 / sysdep-cancel.h
1 /* Copyright (C) 2002, 2003 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Jakub Jelinek <jakub@redhat.com>, 2002.
4
5    The GNU C Library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    The GNU C Library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15    You should have received a copy of the GNU Lesser General Public
16    License along with the GNU C Library; if not, write to the Free
17    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18    02111-1307 USA.  */
19
20 #include <sysdep.h>
21 #include <tls.h>
22 #ifndef __ASSEMBLER__
23 # include <nptl/pthreadP.h>
24 #endif
25
26 #if !defined NOT_IN_libc || defined IS_IN_libpthread
27
28 # undef PSEUDO
29 # define PSEUDO(name, syscall_name, args)                                     \
30   .text;                                                                      \
31   ENTRY (name)                                                                \
32   L(name##START):                                                             \
33     SINGLE_THREAD_P;                                                          \
34     jne L(pseudo_cancel);                                                     \
35     DO_CALL (syscall_name, args);                                             \
36     cmpq $-4095, %rax;                                                        \
37     jae SYSCALL_ERROR_LABEL;                                                  \
38     ret;                                                                      \
39   L(pseudo_cancel):                                                           \
40     /* Save registers that might get destroyed.  */                           \
41     SAVESTK_##args                                                            \
42     PUSHARGS_##args                                                           \
43     CENABLE                                                                   \
44     /* Restore registers.  */                                                 \
45     POPARGS_##args                                                            \
46     /* The return value from CENABLE is argument for CDISABLE.  */            \
47     movq %rax, (%rsp);                                                        \
48     movq $SYS_ify (syscall_name), %rax;                                       \
49     syscall;                                                                  \
50     movq (%rsp), %rdi;                                                        \
51     /* Save %rax since it's the error code from the syscall.  */              \
52     movq %rax, 8(%rsp);                                                       \
53     CDISABLE                                                                  \
54     movq 8(%rsp), %rax;                                                       \
55     RESTSTK_##args                                                            \
56     cmpq $-4095, %rax;                                                        \
57     jae SYSCALL_ERROR_LABEL;                                                  \
58   L(pseudo_end):                                                              \
59                                                                               \
60   /* Create unwinding information for the syscall wrapper.  */                \
61   .section .eh_frame,"a",@progbits;                                           \
62   L(STARTFRAME):                                                              \
63     /* Length of the CIE.  */                                                 \
64     .long L(ENDCIE)-L(STARTCIE);                                              \
65   L(STARTCIE):                                                                \
66     /* CIE ID.  */                                                            \
67     .long 0;                                                                  \
68     /* Version number.  */                                                    \
69     .byte 1;                                                                  \
70     /* NUL-terminated augmentation string.  Note "z" means there is an        \
71        augmentation value later on.  */                                       \
72     .string "zR";                                                             \
73     /* Code alignment factor.  */                                             \
74     .uleb128 1;                                                               \
75     /* Data alignment factor.  */                                             \
76     .sleb128 -8;                                                              \
77     /* Return address register column.  */                                    \
78     .byte 16;                                                                 \
79     /* Augmentation value length.  */                                         \
80     .uleb128 1;                                                               \
81     /* Encoding: DW_EH_PE_pcrel + DW_EH_PE_sdata4.  */                        \
82     .byte 0x1b;                                                               \
83     /* Start of the table initialization.  */                                 \
84     .byte 0xc;                                                                \
85     .uleb128 7;                                                               \
86     .uleb128 8;                                                               \
87     .byte 0x90;                                                               \
88     .uleb128 1;                                                               \
89     .align 8;                                                                 \
90   L(ENDCIE):                                                                  \
91     /* Length of the FDE.  */                                                 \
92     .long L(ENDFDE)-L(STARTFDE);                                              \
93   L(STARTFDE):                                                                \
94     /* CIE pointer.  */                                                       \
95     .long L(STARTFDE)-L(STARTFRAME);                                          \
96     /* PC-relative start address of the code.  */                             \
97     .long L(name##START)-.;                                                   \
98     /* Length of the code.  */                                                \
99     .long L(name##END)-L(name##START);                                        \
100     /* No augmentation data.  */                                              \
101     .uleb128 0;                                                               \
102     /* The rest of the code depends on the number of parameters the syscall   \
103        takes.  */                                                             \
104     EH_FRAME_##args(name);                                                    \
105     .align 4;                                                                 \
106   L(ENDFDE):                                                                  \
107   .previous
108
109 # define EH_FRAME_0(name) \
110     .byte 4;                                                                  \
111     .long L(SAVESTK)-L(name##START);                                          \
112     .byte 14;                                                                 \
113     .uleb128 32;                                                              \
114     .byte 4;                                                                  \
115     .long L(RESTSTK)-L(SAVESTK);                                              \
116     .byte 14;                                                                 \
117     .uleb128 8;                                                               \
118     .align 8
119
120 # define EH_FRAME_1(name) EH_FRAME_0 (name)
121 # define EH_FRAME_2(name) EH_FRAME_1 (name)
122
123 # define EH_FRAME_3(name) \
124     .byte 4;                                                                  \
125     .long L(SAVESTK)-L(name##START);                                          \
126     .byte 14;                                                                 \
127     .uleb128 48;                                                              \
128     .byte 4;                                                                  \
129     .long L(RESTSTK)-L(SAVESTK);                                              \
130     .byte 14;                                                                 \
131     .uleb128 8;                                                               \
132     .align 8
133
134 # define EH_FRAME_4(name) EH_FRAME_3 (name)
135
136 # define EH_FRAME_5(name) \
137     .byte 4;                                                                  \
138     .long L(SAVESTK)-L(name##START);                                          \
139     .byte 14;                                                                 \
140     .uleb128 64;                                                              \
141     .byte 4;                                                                  \
142     .long L(RESTSTK)-L(SAVESTK);                                              \
143     .byte 14;                                                                 \
144     .uleb128 8;                                                               \
145     .align 8
146
147 # define EH_FRAME_6(name) EH_FRAME_5 (name)
148
149
150 # undef ASM_SIZE_DIRECTIVE
151 # define ASM_SIZE_DIRECTIVE(name) L(name##END): .size name,.-name;
152
153 # define PUSHARGS_0     /* Nothing.  */
154 # define PUSHARGS_1     PUSHARGS_0 movq %rdi, 8(%rsp);
155 # define PUSHARGS_2     PUSHARGS_1 movq %rsi, 16(%rsp);
156 # define PUSHARGS_3     PUSHARGS_2 movq %rdx, 24(%rsp);
157 # define PUSHARGS_4     PUSHARGS_3 movq %rcx, 32(%rsp);
158 # define PUSHARGS_5     PUSHARGS_4 movq %r8, 40(%rsp);
159 # define PUSHARGS_6     PUSHARGS_5 movq %r9, 48(%rsp);
160
161 # define POPARGS_0      /* Nothing.  */
162 # define POPARGS_1      POPARGS_0 movq 8(%rsp), %rdi;
163 # define POPARGS_2      POPARGS_1 movq 16(%rsp), %rsi;
164 # define POPARGS_3      POPARGS_2 movq 24(%rsp), %rdx;
165 # define POPARGS_4      POPARGS_3 movq 32(%rsp), %r10;
166 # define POPARGS_5      POPARGS_4 movq 40(%rsp), %r8;
167 # define POPARGS_6      POPARGS_5 movq 48(%rsp), %r9;
168
169 /* We always have to align the stack before calling a function.  */
170 # define SAVESTK_0      subq $24, %rsp; L(SAVESTK):
171 # define SAVESTK_1      SAVESTK_0
172 # define SAVESTK_2      SAVESTK_1
173 # define SAVESTK_3      subq $40, %rsp; L(SAVESTK):
174 # define SAVESTK_4      SAVESTK_3
175 # define SAVESTK_5      subq $56, %rsp; L(SAVESTK):
176 # define SAVESTK_6      SAVESTK_5
177
178 # define RESTSTK_0      addq $24,%rsp; L(RESTSTK):
179 # define RESTSTK_1      RESTSTK_0
180 # define RESTSTK_2      RESTSTK_1
181 # define RESTSTK_3      addq $40, %rsp; L(RESTSTK):
182 # define RESTSTK_4      RESTSTK_3
183 # define RESTSTK_5      addq $56, %rsp; L(RESTSTK):
184 # define RESTSTK_6      RESTSTK_5
185
186 # ifdef IS_IN_libpthread
187 #  define CENABLE       call __pthread_enable_asynccancel;
188 #  define CDISABLE      call __pthread_disable_asynccancel;
189 #  define __local_multiple_threads __pthread_multiple_threads
190 # else
191 #  define CENABLE       call __libc_enable_asynccancel;
192 #  define CDISABLE      call __libc_disable_asynccancel;
193 #  define __local_multiple_threads __libc_multiple_threads
194 # endif
195
196 # ifndef __ASSEMBLER__
197 extern int __local_multiple_threads attribute_hidden;
198 #   define SINGLE_THREAD_P \
199   __builtin_expect (__local_multiple_threads == 0, 1)
200 # else
201 #  define SINGLE_THREAD_P cmpl $0, __local_multiple_threads(%rip)
202 # endif
203
204 #elif !defined __ASSEMBLER__
205
206 /* This code should never be used but we define it anyhow.  */
207 # define SINGLE_THREAD_P (1)
208
209 #endif