2 /*--------------------------------------------------------------------*/
3 /*--- Support for doing system calls. syscall-x86-solaris.S ---*/
4 /*--------------------------------------------------------------------*/
7 This file is part of Valgrind, a dynamic binary instrumentation
10 Copyright (C) 2011-2014 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 #if defined(VGP_x86_solaris)
33 #include "pub_core_basics_asm.h"
34 #include "pub_core_vkiscnums_asm.h"
35 #include "libvex_guest_offsets.h"
37 /* From vki-solaris.h, checked at startup by m_vki.c. */
38 #define VKI_SIG_SETMASK 3
41 Int ML_(do_syscall_for_client_WRK)(
42 Int syscallno, // %ebp+8
43 void *guest_state, // %ebp+12
44 const vki_sigset_t *sysmask, // %ebp+16
45 const vki_sigset_t *postmask, // %ebp+20
46 UChar *cflag) // %ebp+24
49 .macro ESTABLISH_STACKFRAME
50 /* Establish stack frame. */
53 pushl %ebx /* save %ebx */
55 /* We'll use %ebx instead of %ebp to address the stack frame after the
56 door syscall is finished because %ebp is cleared by the syscall. */
57 movl %esp, %ebx /* %ebx = %ebp - 4 */
60 .macro UNBLOCK_SIGNALS
61 /* Set the signal mask which should be current during the syscall. */
62 /* Set up for sigprocmask(SIG_SETMASK, sysmask, postmask). */
65 pushl $VKI_SIG_SETMASK
66 pushl $0xcafebabe /* totally fake return address */
67 movl $__NR_sigprocmask, %eax
69 jc sigprocmask_failed /* sigprocmask failed */
73 .macro REBLOCK_SIGNALS
74 /* Set up for sigprocmask(SIG_SETMASK, postmask, NULL). */
77 pushl $VKI_SIG_SETMASK
78 pushl $0xcafef00d /* totally fake return address */
79 movl $__NR_sigprocmask, %eax
81 /* The syscall above changes the carry flag. This means that if the
82 syscall fails and we receive an interrupt after it then we've got
83 an invalid carry flag value in the fixup code. We don't care about
84 it because this syscall should never fail and if it does then we're
85 going to stop Valgrind anyway. */
86 jc sigprocmask_failed /* sigprocmask failed */
91 xorl %eax, %eax /* SUCCESS */
92 movl -4(%ebp), %ebx /* restore %ebx */
99 /* Failure: return 0x8000 | error code. */
100 /* Note that we enter here with %esp being 16 too low (4 extra words
101 on the stack). But because we're nuking the stack frame now, that
105 movl -4(%ebp), %ebx /* restore %ebx */
110 .globl ML_(do_syscall_for_client_WRK)
111 ML_(do_syscall_for_client_WRK):
114 1: /* Even though we can't take a signal until the sigprocmask completes,
115 start the range early. If %eip is in the range [1, 2), the syscall
116 hasn't been started yet. */
119 /* Copy syscall parameters to the stack - assume no more than 8 plus
120 the return address. */
123 movl OFFSET_x86_ESP(%edx), %edx /* %edx = simulated ESP */
124 movl 28+4(%edx), %eax
126 movl 24+4(%edx), %eax
128 movl 20+4(%edx), %eax
130 movl 16+4(%edx), %eax
132 movl 12+4(%edx), %eax
140 /* Return address. */
144 /* Put syscall number in %eax. */
147 /* Do the syscall. Note that the Solaris kernel doesn't directly
151 2: /* In the range [2, 3), the syscall result is in %eax and %edx and C,
152 but hasn't been committed to the thread state. If we get
153 interrupted in this section then we'll just use values saved in the
156 Important note for this and the following section: Don't add here
157 any code that alters the carry flag or worse, call any function.
158 That would completely break the fixup after an interrupt. */
160 movl %eax, OFFSET_x86_EAX(%ecx) /* save %eax to VEX */
161 movl %edx, OFFSET_x86_EDX(%ecx) /* save %edx to VEX */
163 setc 0(%ecx) /* save returned carry flag */
165 3: /* Re-block signals. If %eip is in [3, 4), then the syscall is
166 complete and we do not need to worry about it. We have to only
167 correctly save the carry flag. If we get interrupted in this
168 section then we just have to propagate the carry flag from the
169 ucontext structure to the thread state, %eax and %edx values are
173 4: /* Now safe from signals. */
177 /* Export the ranges so that
178 VG_(fixup_guest_state_after_syscall_interrupted) can do the right thing. */
180 .globl ML_(blksys_setup)
181 .globl ML_(blksys_complete)
182 .globl ML_(blksys_committed)
183 .globl ML_(blksys_finished)
184 ML_(blksys_setup): .long 1b
185 ML_(blksys_complete): .long 2b
186 ML_(blksys_committed): .long 3b
187 ML_(blksys_finished): .long 4b
191 Int ML_(do_syscall_for_client_dret_WRK)(
192 Int syscallno, // %ebp+8 = %ebx+8+4
193 void *guest_state, // %ebp+12 = %ebx+12+4
194 const vki_sigset_t *sysmask, // %ebp+16 = %ebx+16+4
195 const vki_sigset_t *postmask, // %ebp+20 = %ebx+20+4
196 UChar *cflag) // %ebp+24 = %ebx+24+4
199 /* Door_return is a very special call because the data are stored by the
200 kernel directly on the stack and the stack pointer is appropriately
201 modified by the kernel. Therefore we switch to the client stack before
202 doing the syscall, this is relatively trivial but an extra care has to be
203 taken when we get interrupted at some point. */
205 .globl ML_(do_syscall_for_client_dret_WRK)
206 ML_(do_syscall_for_client_dret_WRK):
209 1: /* Even though we can't take a signal until the sigprocmask completes,
210 start the range early. If %eip is in the range [1, 2), the syscall
211 hasn't been started yet. */
214 /* Switch to the client stack. */
216 movl OFFSET_x86_ESP(%edx), %esp /* %esp = simulated ESP */
217 /* Change %ebp to a client value. It will always get committed by
218 the fixup code for range [2, 3) so it needs to be set to what the
220 movl OFFSET_x86_EBP(%edx), %ebp /* %ebp = simulated EBP */
222 /* Put syscall number in %eax. */
225 /* Do the syscall. Note that the Solaris kernel doesn't directly
229 2: /* In the range [2, 3), the syscall result is in %eax, %edx, %esp and
230 %ebp and C, but hasn't been committed to the thread state. If we
231 get interrupted in this section then we'll just use values saved in
232 the ucontext structure.
234 Important note for this and the following section: Don't add here
235 any code that alters the carry flag or worse, call any function.
236 That would completely break the fixup after an interrupt. */
237 movl 12+4(%ebx), %ecx
238 movl %eax, OFFSET_x86_EAX(%ecx) /* save %eax to VEX */
239 movl %edx, OFFSET_x86_EDX(%ecx) /* save %edx to VEX */
240 movl %esp, OFFSET_x86_ESP(%ecx) /* save %esp to VEX */
241 movl %ebp, OFFSET_x86_EBP(%ecx) /* save %ebp to VEX */
242 movl 24+4(%ebx), %ecx
243 setc 0(%ecx) /* save returned carry flag */
245 movl %ebx, %esp /* switch to V stack */
247 3: /* Re-block signals. If %eip is in [3, 4), then the syscall is
248 complete and we do not need worry about it. We have to only
249 correctly save the carry flag. If we get interrupted in this
250 section then we just have to propagate the carry flag from the
251 ucontext structure to the thread state, %eax, %edx, %esp and %ebp
252 values are already saved. */
257 4: /* Now safe from signals. */
261 .globl ML_(blksys_setup_DRET)
262 .globl ML_(blksys_complete_DRET)
263 .globl ML_(blksys_committed_DRET)
264 .globl ML_(blksys_finished_DRET)
265 ML_(blksys_setup_DRET): .long 1b
266 ML_(blksys_complete_DRET): .long 2b
267 ML_(blksys_committed_DRET): .long 3b
268 ML_(blksys_finished_DRET): .long 4b
271 #endif // defined(VGP_x86_solaris)
273 /*--------------------------------------------------------------------*/
275 /*--------------------------------------------------------------------*/