2 /*--------------------------------------------------------------------*/
3 /*--- Support for doing system calls. syscall-amd64-solaris.S ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2014-2017 Petr Pavlu
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
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
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. */
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 */
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). */
73 movq $VKI_SIG_SETMASK, %rdi
74 movq $__NR_sigprocmask, %rax
76 jc sigprocmask_failed /* sigprocmask failed */
79 .macro REBLOCK_SIGNALS
80 /* Set up for sigprocmask(SIG_SETMASK, postmask, NULL). */
83 movq $VKI_SIG_SETMASK, %rdi
84 movq $__NR_sigprocmask, %rax
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 */
95 xorq %rax, %rax /* SUCCESS */
96 movq -8(%rbp), %rbx /* restore %rbx */
103 /* Failure: return 0x8000 | error code. */
106 movq -8(%rbp), %rbx /* restore %rbx */
111 .globl ML_(do_syscall_for_client_WRK)
112 ML_(do_syscall_for_client_WRK):
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. */
120 /* Copy syscall parameters. */
122 /* 6 register parameters. */
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
136 /* Return address. */
140 /* Put syscall number in %rax. */
143 /* Do the syscall. Note that the Solaris kernel doesn't directly
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
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. */
156 movq %rax, OFFSET_amd64_RAX(%rcx) /* save %rax to VEX */
157 movq %rdx, OFFSET_amd64_RDX(%rcx) /* save %rdx to VEX */
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
169 4: /* Now safe from signals. */
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
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):
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. */
210 /* Prepare 6 register parameters. */
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
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
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. */
261 4: /* Now safe from signals. */
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
275 #endif // defined(VGP_amd64_solaris)
277 /* Let the linker know we don't need an executable stack */
280 /*--------------------------------------------------------------------*/
282 /*--------------------------------------------------------------------*/