blob: 391c48da35d141b96c92c924f29e32784ef2085f [file] [log] [blame]
sewardj8eb8bab2015-07-21 14:44:28 +00001
2/*--------------------------------------------------------------------*/
3/*--- Support for doing system calls. syscall-amd64-solaris.S ---*/
4/*--------------------------------------------------------------------*/
5
6/*
7 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
9
Elliott Hughesed398002017-06-21 14:41:24 -070010 Copyright (C) 2014-2017 Petr Pavlu
sewardj8eb8bab2015-07-21 14:44:28 +000011 setup@dagobah.cz
12
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.
17
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.
22
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.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
florian3f1d6132015-09-30 20:30:48 +000031#include "pub_core_basics_asm.h"
32
sewardj8eb8bab2015-07-21 14:44:28 +000033#if defined(VGP_amd64_solaris)
34
sewardj8eb8bab2015-07-21 14:44:28 +000035#include "pub_core_vkiscnums_asm.h"
36#include "libvex_guest_offsets.h"
37
38/* From vki-solaris.h, checked at startup by m_vki.c. */
39#define VKI_SIG_SETMASK 3
40
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
48*/
49
50.macro ESTABLISH_STACKFRAME
51 /* Establish stack frame. */
52 pushq %rbp
53 movq %rsp, %rbp
54 pushq %rbx /* save %rbx */
55
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 */
59
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
67
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
78
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
93
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
101
102sigprocmask_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
110
111.globl ML_(do_syscall_for_client_WRK)
112ML_(do_syscall_for_client_WRK):
113 ESTABLISH_STACKFRAME
114
1151: /* 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
119
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
139
140 /* Put syscall number in %rax. */
141 movq -48(%rbp), %rax
142
143 /* Do the syscall. Note that the Solaris kernel doesn't directly
144 restart syscalls! */
145 syscall
146
1472: /* 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.
151
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 */
160
1613: /* 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
168
1694: /* Now safe from signals. */
170 SIMPLE_RETURN
171
172.section .rodata
173/* Export the ranges so that
174 VG_(fixup_guest_state_after_syscall_interrupted) can do the right thing. */
175
176.globl ML_(blksys_setup)
177.globl ML_(blksys_complete)
178.globl ML_(blksys_committed)
179.globl ML_(blksys_finished)
180ML_(blksys_setup): .quad 1b
181ML_(blksys_complete): .quad 2b
182ML_(blksys_committed): .quad 3b
183ML_(blksys_finished): .quad 4b
184.previous
185
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
193*/
194
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. */
200
201.globl ML_(do_syscall_for_client_dret_WRK)
202ML_(do_syscall_for_client_dret_WRK):
203 ESTABLISH_STACKFRAME
204
2051: /* 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
209
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
218
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 */
225
226 /* Put syscall number in %rax. */
227 movq -48+8(%rbx), %rax
228
229 /* Do the syscall. Note that the Solaris kernel doesn't directly
230 restart syscalls! */
231 syscall
232
2332: /* 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.
237
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 */
248
249 movq %rbx, %rsp /* switch to V stack */
250
2513: /* 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
260
2614: /* Now safe from signals. */
262 SIMPLE_RETURN
263
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)
269ML_(blksys_setup_DRET): .quad 1b
270ML_(blksys_complete_DRET): .quad 2b
271ML_(blksys_committed_DRET): .quad 3b
272ML_(blksys_finished_DRET): .quad 4b
273.previous
274
275#endif // defined(VGP_amd64_solaris)
276
florian3f1d6132015-09-30 20:30:48 +0000277/* Let the linker know we don't need an executable stack */
278MARK_STACK_NO_EXEC
279
sewardj8eb8bab2015-07-21 14:44:28 +0000280/*--------------------------------------------------------------------*/
281/*--- end ---*/
282/*--------------------------------------------------------------------*/