drd/tests: Fix remaining gcc 8 compiler warnings
[valgrind.git] / coregrind / m_syswrap / syscall-amd64-solaris.S
blob391c48da35d141b96c92c924f29e32784ef2085f
2 /*--------------------------------------------------------------------*/
3 /*--- Support for doing system calls.      syscall-amd64-solaris.S ---*/
4 /*--------------------------------------------------------------------*/
6 /*
7   This file is part of Valgrind, a dynamic binary instrumentation
8   framework.
10   Copyright (C) 2014-2017 Petr Pavlu
11      setup@dagobah.cz
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 #include "pub_core_basics_asm.h"
33 #if defined(VGP_amd64_solaris)
35 #include "pub_core_vkiscnums_asm.h"
36 #include "libvex_guest_offsets.h"
38 /* From vki-solaris.h, checked at startup by m_vki.c. */
39 #define VKI_SIG_SETMASK 3
41 /* Prototype:
42    Int ML_(do_syscall_for_client_WRK)(
43       Int syscallno,                    // %rdi = %rbp-48
44       void *guest_state,                // %rsi = %rbp-40
45       const vki_sigset_t *sysmask,      // %rdx = %rbp-32
46       const vki_sigset_t *postmask,     // %rcx = %rbp-24
47       UChar *cflag)                     // %r8 = %rbp-16
50 .macro ESTABLISH_STACKFRAME
51         /* Establish stack frame. */
52         pushq   %rbp
53         movq    %rsp, %rbp
54         pushq   %rbx                            /* save %rbx */
56         /* We'll use %rbx instead of %rbp to address the stack frame after the
57            door syscall is finished because %rbp is cleared by the syscall. */
58         movq    %rsp, %rbx                      /* %rbx = %rbp - 8 */
60         /* Push the parameters on the stack. */
61         pushq   %r8                             /* store %r8 at %rbp-16 */
62         pushq   %rcx                            /* store %rcx at %rbp-24 */
63         pushq   %rdx                            /* store %rdx at %rbp-32 */
64         pushq   %rsi                            /* store %rsi at %rbp-40 */
65         pushq   %rdi                            /* store %rdi at %rbp-48 */
66 .endm
68 .macro UNBLOCK_SIGNALS
69         /* Set the signal mask which should be current during the syscall. */
70         /* Set up for sigprocmask(SIG_SETMASK, sysmask, postmask). */
71         movq    -24(%rbp), %rdx
72         movq    -32(%rbp), %rsi
73         movq    $VKI_SIG_SETMASK, %rdi
74         movq    $__NR_sigprocmask, %rax
75         syscall
76         jc      sigprocmask_failed              /* sigprocmask failed */
77 .endm
79 .macro REBLOCK_SIGNALS
80         /* Set up for sigprocmask(SIG_SETMASK, postmask, NULL). */
81         movq    $0, %rdx
82         movq    -24(%rbp), %rsi
83         movq    $VKI_SIG_SETMASK, %rdi
84         movq    $__NR_sigprocmask, %rax
85         syscall
86         /* The syscall above changes the carry flag.  This means that if the
87            syscall fails and we receive an interrupt after it then we've got
88            an invalid carry flag value in the fixup code.  We don't care about
89            it because this syscall should never fail and if it does then we're
90            going to stop Valgrind anyway. */
91         jc      sigprocmask_failed              /* sigprocmask failed */
92 .endm
94 .macro SIMPLE_RETURN
95         xorq    %rax, %rax                      /* SUCCESS */
96         movq    -8(%rbp), %rbx                  /* restore %rbx */
97         movq    %rbp, %rsp
98         popq    %rbp
99         ret
100 .endm
102 sigprocmask_failed:
103         /* Failure: return 0x8000 | error code. */
104         andq    $0x7FFF, %rax
105         orq     $0x8000, %rax
106         movq    -8(%rbp), %rbx                  /* restore %rbx */
107         movq    %rbp, %rsp
108         popq    %rbp
109         ret
111 .globl ML_(do_syscall_for_client_WRK)
112 ML_(do_syscall_for_client_WRK):
113         ESTABLISH_STACKFRAME
115 1:      /* Even though we can't take a signal until the sigprocmask completes,
116            start the range early.  If %rip is in the range [1, 2), the syscall
117            hasn't been started yet. */
118         UNBLOCK_SIGNALS
120         /* Copy syscall parameters. */
121         /* do_syscall8 */
122         /* 6 register parameters. */
123         movq    -40(%rbp), %rax
124         movq    OFFSET_amd64_RDI(%rax), %rdi
125         movq    OFFSET_amd64_RSI(%rax), %rsi
126         movq    OFFSET_amd64_RDX(%rax), %rdx
127         movq    OFFSET_amd64_R10(%rax), %r10
128         movq    OFFSET_amd64_R8(%rax), %r8
129         movq    OFFSET_amd64_R9(%rax), %r9
130         /* 2 stack parameters. */
131         movq    OFFSET_amd64_RSP(%rax), %rax
132         movq    16(%rax), %r11
133         pushq   %r11
134         movq    8(%rax), %r11
135         pushq   %r11
136         /* Return address. */
137         movq    0(%rax), %r11
138         pushq   %r11
140         /* Put syscall number in %rax. */
141         movq    -48(%rbp), %rax
143         /* Do the syscall.  Note that the Solaris kernel doesn't directly
144            restart syscalls! */
145         syscall
147 2:      /* In the range [2, 3), the syscall result is in %rax and %rdx and C,
148            but hasn't been committed to the thread state.  If we get
149            interrupted in this section then we'll just use values saved in the
150            ucontext structure.
152            Important note for this and the following section: Don't add here
153            any code that alters the carry flag or worse, call any function.
154            That would completely break the fixup after an interrupt. */
155         movq    -40(%rbp), %rcx
156         movq    %rax, OFFSET_amd64_RAX(%rcx)    /* save %rax to VEX */
157         movq    %rdx, OFFSET_amd64_RDX(%rcx)    /* save %rdx to VEX */
158         movq    -16(%rbp), %rcx
159         setc    0(%rcx)                         /* save returned carry flag */
161 3:      /* Re-block signals. If %rip is in [3, 4), then the syscall is
162            complete and we do not need to worry about it.  We have to only
163            correctly save the carry flag.  If we get interrupted in this
164            section then we just have to propagate the carry flag from the
165            ucontext structure to the thread state, %rax and %rdx values are
166            already saved. */
167         REBLOCK_SIGNALS
169 4:      /* Now safe from signals. */
170         SIMPLE_RETURN
172 .section .rodata
173 /* Export the ranges so that
174    VG_(fixup_guest_state_after_syscall_interrupted) can do the right thing. */
176 .globl ML_(blksys_setup)
177 .globl ML_(blksys_complete)
178 .globl ML_(blksys_committed)
179 .globl ML_(blksys_finished)
180 ML_(blksys_setup):      .quad 1b
181 ML_(blksys_complete):   .quad 2b
182 ML_(blksys_committed):  .quad 3b
183 ML_(blksys_finished):   .quad 4b
184 .previous
186 /* Prototype:
187    Int ML_(do_syscall_for_client_dret_WRK)(
188       Int syscallno,                    // %rdi = %rbp-48 = %rbx-48+8
189       void *guest_state,                // %rsi = %rbp-40 = %rbx-40+8
190       const vki_sigset_t *sysmask,      // %rdx = %rbp-32 = %rbx-32+8
191       const vki_sigset_t *postmask,     // %rcx = %rbp-24 = %rbx-24+8
192       UChar *cflag)                     // %r8 = %rbp-16 = %rbx-16+8
195 /* Door_return is a very special call because the data are stored by the
196    kernel directly on the stack and the stack pointer is appropriately
197    modified by the kernel.  Therefore we switch to the client stack before
198    doing the syscall, this is relatively trivial but an extra care has to be
199    taken when we get interrupted at some point. */
201 .globl ML_(do_syscall_for_client_dret_WRK)
202 ML_(do_syscall_for_client_dret_WRK):
203         ESTABLISH_STACKFRAME
205 1:      /* Even though we can't take a signal until the sigprocmask completes,
206            start the range early.  If %rip is in the range [1, 2), the syscall
207            hasn't been started yet. */
208         UNBLOCK_SIGNALS
210         /* Prepare 6 register parameters. */
211         movq    -40(%rbp), %rax
212         movq    OFFSET_amd64_RDI(%rax), %rdi
213         movq    OFFSET_amd64_RSI(%rax), %rsi
214         movq    OFFSET_amd64_RDX(%rax), %rdx
215         movq    OFFSET_amd64_R10(%rax), %r10
216         movq    OFFSET_amd64_R8(%rax), %r8
217         movq    OFFSET_amd64_R9(%rax), %r9
219         /* Switch to the client stack. */
220         movq    OFFSET_amd64_RSP(%rax), %rsp    /* %rsp = simulated RSP */
221         /* Change %rbp to a client value. It will always get committed by
222            the fixup code for range [2, 3) so it needs to be set to what the
223            client expects. */
224         movq    OFFSET_amd64_RBP(%rax), %rbp    /* %rbp = simulated RBP */
226         /* Put syscall number in %rax. */
227         movq    -48+8(%rbx), %rax
229         /* Do the syscall.  Note that the Solaris kernel doesn't directly
230            restart syscalls! */
231         syscall
233 2:      /* In the range [2, 3), the syscall result is in %rax, %rdx, %rsp and
234            %rbp and C, but hasn't been committed to the thread state.  If we
235            get interrupted in this section then we'll just use values saved in
236            the ucontext structure.
238            Important note for this and the following section: Don't add here
239            any code that alters the carry flag or worse, call any function.
240            That would completely break the fixup after an interrupt. */
241         movq    -40+8(%rbx), %rcx
242         movq    %rax, OFFSET_amd64_RAX(%rcx)    /* save %rax to VEX */
243         movq    %rdx, OFFSET_amd64_RDX(%rcx)    /* save %rdx to VEX */
244         movq    %rsp, OFFSET_amd64_RSP(%rcx)    /* save %rsp to VEX */
245         movq    %rbp, OFFSET_amd64_RBP(%rcx)    /* save %rbp to VEX */
246         movq    -16+8(%rbx), %rcx
247         setc    0(%rcx)                         /* save returned carry flag */
249         movq    %rbx, %rsp                      /* switch to V stack */
251 3:      /* Re-block signals. If %rip is in [3, 4), then the syscall is
252            complete and we do not need worry about it.  We have to only
253            correctly save the carry flag.  If we get interrupted in this
254            section then we just have to propagate the carry flag from the
255            ucontext structure to the thread state, %rax, %rdx, %rsp and %rbp
256            values are already saved. */
257         movq    %rbx, %rbp
258         addq    $8, %rbp
259         REBLOCK_SIGNALS
261 4:      /* Now safe from signals. */
262         SIMPLE_RETURN
264 .section .rodata
265 .globl ML_(blksys_setup_DRET)
266 .globl ML_(blksys_complete_DRET)
267 .globl ML_(blksys_committed_DRET)
268 .globl ML_(blksys_finished_DRET)
269 ML_(blksys_setup_DRET):         .quad 1b
270 ML_(blksys_complete_DRET):      .quad 2b
271 ML_(blksys_committed_DRET):     .quad 3b
272 ML_(blksys_finished_DRET):      .quad 4b
273 .previous
275 #endif // defined(VGP_amd64_solaris)
277 /* Let the linker know we don't need an executable stack */
278 MARK_STACK_NO_EXEC
280 /*--------------------------------------------------------------------*/
281 /*--- end                                                          ---*/
282 /*--------------------------------------------------------------------*/