tests/vg_regtest: Always evaluate prerequisite expressions with sh
[valgrind.git] / coregrind / m_syswrap / syscall-amd64-linux.S
bloba6d74690ecc4e0d99d891da0dec418b261ba78ec
2 /*--------------------------------------------------------------------*/
3 /*--- Support for doing system calls.        syscall-amd64-linux.S ---*/
4 /*--------------------------------------------------------------------*/
6 /*
7   This file is part of Valgrind, a dynamic binary instrumentation
8   framework.
10   Copyright (C) 2000-2013 Julian Seward 
11      jseward@acm.org
13   This program is free software; you can redistribute it and/or
14   modify it under the terms of the GNU General Public License as
15   published by the Free Software Foundation; either version 2 of the
16   License, or (at your option) any later version.
18   This program is distributed in the hope that it will be useful, but
19   WITHOUT ANY WARRANTY; without even the implied warranty of
20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21   General Public License for more details.
23   You should have received a copy of the GNU General Public License
24   along with this program; if not, write to the Free Software
25   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26   02111-1307, USA.
28   The GNU General Public License is contained in the file COPYING.
31 #if defined(VGP_amd64_linux)
33 #include "pub_core_basics_asm.h"
34 #include "pub_core_vkiscnums_asm.h"
35 #include "libvex_guest_offsets.h"
38 /*----------------------------------------------------------------*/
40         Perform a syscall for the client.  This will run a syscall
41         with the client's specific per-thread signal mask.
42         
43         The structure of this function is such that, if the syscall is
44         interrupted by a signal, we can determine exactly what
45         execution state we were in with respect to the execution of
46         the syscall by examining the value of %eip in the signal
47         handler.  This means that we can always do the appropriate
48         thing to precisely emulate the kernel's signal/syscall
49         interactions.
51         The syscall number is taken from the argument, even though it
52         should also be in guest_state->guest_RAX.  The syscall result
53         is written back to guest_state->guest_RAX on completion.
54         
55         Returns 0 if the syscall was successfully called (even if the
56         syscall itself failed), or a -ve error code if one of the
57         sigprocmasks failed (there's no way to determine which one
58         failed).
60         VG_(fixup_guest_state_after_syscall_interrupted) does the
61         thread state fixup in the case where we were interrupted by a
62         signal.
63         
64         Prototype:
66         Int ML_(do_syscall_for_client_WRK(
67                                   Int syscallno,                // rdi
68                                   void* guest_state,            // rsi
69                                   const vki_sigset_t *sysmask,  // rdx
70                                   const vki_sigset_t *postmask, // rcx
71                                   Int sigsetSzB)                // r8
72                                    
75 /* from vki_arch.h */   
76 #define VKI_SIG_SETMASK 2
77         
78 .globl ML_(do_syscall_for_client_WRK)
79 ML_(do_syscall_for_client_WRK):
80         .cfi_startproc
81         /* save callee-saved regs */
82         pushq   %rbx
83         .cfi_adjust_cfa_offset 8
84         .cfi_offset %rbx, -16
85         pushq   %rbp
86         .cfi_adjust_cfa_offset 8
87         .cfi_offset %rbp, -24
88         pushq   %r12
89         .cfi_adjust_cfa_offset 8
90         .cfi_offset %r12, -32
91         pushq   %r13
92         .cfi_adjust_cfa_offset 8
93         .cfi_offset %r13, -40
94         pushq   %r14
95         .cfi_adjust_cfa_offset 8
96         .cfi_offset %r14, -48
97         pushq   %r15
98         .cfi_adjust_cfa_offset 8
99         .cfi_offset %r15, -56
101 #define FSZ     ((4+1)*4)       /* 4 args + ret addr */
103 #define PUSH_di_si_dx_cx_8         \
104         pushq   %rdi ;             \
105         .cfi_adjust_cfa_offset 8 ; \
106         pushq   %rsi ;             \
107         .cfi_adjust_cfa_offset 8 ; \
108         pushq   %rdx ;             \
109         .cfi_adjust_cfa_offset 8 ; \
110         pushq   %rcx ;             \
111         .cfi_adjust_cfa_offset 8 ; \
112         pushq   %r8 ;              \
113         .cfi_adjust_cfa_offset 8
115 #define POP_di_si_dx_cx_8           \
116         popq    %r8 ;               \
117         .cfi_adjust_cfa_offset -8 ; \
118         popq    %rcx ;              \
119         .cfi_adjust_cfa_offset -8 ; \
120         popq    %rdx ;              \
121         .cfi_adjust_cfa_offset -8 ; \
122         popq    %rsi ;              \
123         .cfi_adjust_cfa_offset -8 ; \
124         popq    %rdi ;              \
125         .cfi_adjust_cfa_offset -8
127 1:      /* Even though we can't take a signal until the sigprocmask completes,
128            start the range early.
129            If eip is in the range [1,2), the syscall hasn't been started yet */
131         /* Set the signal mask which should be current during the syscall. */
132         /* Save and restore all 5 arg regs round the call.  This is easier
133            than figuring out the minimal set to save/restore. */
135         PUSH_di_si_dx_cx_8
137         movq    $__NR_rt_sigprocmask, %rax      // syscall #
138         movq    $VKI_SIG_SETMASK, %rdi          // how
139         movq    %rdx, %rsi                      // sysmask
140         movq    %rcx, %rdx                      // postmask
141         movq    %r8, %r10                       // sigsetSzB
142         syscall
144         POP_di_si_dx_cx_8
145         
146         testq   %rax, %rax
147         js      7f      /* sigprocmask failed */
149         /* OK, that worked.  Now do the syscall proper. */
150         
151         PUSH_di_si_dx_cx_8
153         movq    %rsi, %rax      /* rax --> VexGuestAMD64State * */
154         pushq   %rdi            /* syscallno -> stack */
155         .cfi_adjust_cfa_offset 8
156         movq    OFFSET_amd64_RDI(%rax), %rdi
157         movq    OFFSET_amd64_RSI(%rax), %rsi
158         movq    OFFSET_amd64_RDX(%rax), %rdx
159         movq    OFFSET_amd64_R10(%rax), %r10
160         movq    OFFSET_amd64_R8(%rax), %r8
161         movq    OFFSET_amd64_R9(%rax), %r9
162         popq    %rax    /* syscallno -> %rax */
163         .cfi_adjust_cfa_offset -8
164         
165         /* If rip==2, then the syscall was either just about
166            to start, or was interrupted and the kernel was 
167            restarting it. */
168 2:      syscall
169 3:      /* In the range [3, 4), the syscall result is in %rax, 
170            but hasn't been committed to RAX. */
172         POP_di_si_dx_cx_8
174         movq    %rax, OFFSET_amd64_RAX(%rsi)    /* save back to RAX */
176 4:      /* Re-block signals.  If eip is in [4,5), then the syscall 
177            is complete and we needn't worry about it. */
179         PUSH_di_si_dx_cx_8
181         movq    $__NR_rt_sigprocmask, %rax      // syscall #
182         movq    $VKI_SIG_SETMASK, %rdi          // how
183         movq    %rcx, %rsi                      // postmask
184         xorq    %rdx, %rdx                      // NULL
185         movq    %r8, %r10                       // sigsetSzB
186         syscall
188         POP_di_si_dx_cx_8
190         testq   %rax, %rax
191         js      7f      /* sigprocmask failed */
193 5:      /* now safe from signals */
194         movq    $0, %rax        /* SUCCESS */
195         popq    %r15
196         .cfi_adjust_cfa_offset -8
197         popq    %r14
198         .cfi_adjust_cfa_offset -8
199         popq    %r13
200         .cfi_adjust_cfa_offset -8
201         popq    %r12
202         .cfi_adjust_cfa_offset -8
203         popq    %rbp
204         .cfi_adjust_cfa_offset -8
205         popq    %rbx
206         .cfi_adjust_cfa_offset -8
207         ret
208         .cfi_adjust_cfa_offset 6*8
210 7:      /* failure:      return 0x8000 | error code */
211         negq    %rax
212         andq    $0x7FFF, %rax
213         orq     $0x8000, %rax
214         popq    %r15
215         .cfi_adjust_cfa_offset -8
216         popq    %r14
217         .cfi_adjust_cfa_offset -8
218         popq    %r13
219         .cfi_adjust_cfa_offset -8
220         popq    %r12
221         .cfi_adjust_cfa_offset -8
222         popq    %rbp
223         .cfi_adjust_cfa_offset -8
224         popq    %rbx
225         .cfi_adjust_cfa_offset -8
226         ret
227         .cfi_endproc
228 #undef FSZ
230 .section .rodata
231 /* export the ranges so that
232    VG_(fixup_guest_state_after_syscall_interrupted) can do the
233    right thing */
234         
235 .globl ML_(blksys_setup)
236 .globl ML_(blksys_restart)
237 .globl ML_(blksys_complete)
238 .globl ML_(blksys_committed)
239 .globl ML_(blksys_finished)
240 ML_(blksys_setup):      .quad 1b
241 ML_(blksys_restart):    .quad 2b
242 ML_(blksys_complete):   .quad 3b
243 ML_(blksys_committed):  .quad 4b
244 ML_(blksys_finished):   .quad 5b
245 .previous
247 /* Let the linker know we don't need an executable stack */
248 .section .note.GNU-stack,"",@progbits
250 #endif // defined(VGP_amd64_linux)
252 /*--------------------------------------------------------------------*/
253 /*--- end                                                          ---*/
254 /*--------------------------------------------------------------------*/