• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1
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
10  Copyright (C) 2014-2015 Petr Pavlu
11     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
31#include "pub_core_basics_asm.h"
32
33#if defined(VGP_amd64_solaris)
34
35#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
277/* Let the linker know we don't need an executable stack */
278MARK_STACK_NO_EXEC
279
280/*--------------------------------------------------------------------*/
281/*--- end                                                          ---*/
282/*--------------------------------------------------------------------*/
283