tests/vg_regtest: Always evaluate prerequisite expressions with sh
[valgrind.git] / coregrind / m_syswrap / syscall-x86-solaris.S
blobcb4346fa715dd6b1581e6d1fd6d51bcded454fa1
2 /*--------------------------------------------------------------------*/
3 /*--- Support for doing system calls.        syscall-x86-solaris.S ---*/
4 /*--------------------------------------------------------------------*/
6 /*
7   This file is part of Valgrind, a dynamic binary instrumentation
8   framework.
10   Copyright (C) 2011-2014 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 #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
40 /* Prototype:
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. */
51         pushl   %ebp
52         movl    %esp, %ebp
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 */
58 .endm
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). */
63         pushl   20(%ebp)
64         pushl   16(%ebp)
65         pushl   $VKI_SIG_SETMASK
66         pushl   $0xcafebabe                     /* totally fake return address */
67         movl    $__NR_sigprocmask, %eax
68         int     $0x91
69         jc      sigprocmask_failed              /* sigprocmask failed */
70         addl    $16, %esp
71 .endm
73 .macro REBLOCK_SIGNALS
74         /* Set up for sigprocmask(SIG_SETMASK, postmask, NULL). */
75         pushl   $0
76         pushl   20(%ebp)
77         pushl   $VKI_SIG_SETMASK
78         pushl   $0xcafef00d                     /* totally fake return address */
79         movl    $__NR_sigprocmask, %eax
80         int     $0x91
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 */
87         addl    $16, %esp
88 .endm
90 .macro SIMPLE_RETURN
91         xorl    %eax, %eax                      /* SUCCESS */
92         movl    -4(%ebp), %ebx                  /* restore %ebx */
93         movl    %ebp, %esp
94         popl    %ebp
95         ret
96 .endm
98 sigprocmask_failed:
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
102            doesn't matter. */
103         andl    $0x7FFF, %eax
104         orl     $0x8000, %eax
105         movl    -4(%ebp), %ebx                  /* restore %ebx */
106         movl    %ebp, %esp
107         popl    %ebp
108         ret
110 .globl ML_(do_syscall_for_client_WRK)
111 ML_(do_syscall_for_client_WRK):
112         ESTABLISH_STACKFRAME
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. */
117         UNBLOCK_SIGNALS
119         /* Copy syscall parameters to the stack - assume no more than 8 plus
120            the return address. */
121         /* do_syscall8 */
122         movl    12(%ebp), %edx
123         movl    OFFSET_x86_ESP(%edx), %edx      /* %edx = simulated ESP */
124         movl    28+4(%edx), %eax
125         pushl   %eax
126         movl    24+4(%edx), %eax
127         pushl   %eax
128         movl    20+4(%edx), %eax
129         pushl   %eax
130         movl    16+4(%edx), %eax
131         pushl   %eax
132         movl    12+4(%edx), %eax
133         pushl   %eax
134         movl    8+4(%edx), %eax
135         pushl   %eax
136         movl    4+4(%edx), %eax
137         pushl   %eax
138         movl    0+4(%edx), %eax
139         pushl   %eax
140         /* Return address. */
141         movl    0(%edx), %eax
142         pushl   %eax
144         /* Put syscall number in %eax. */
145         movl    8(%ebp), %eax
147         /* Do the syscall.  Note that the Solaris kernel doesn't directly
148            restart syscalls! */
149         int     $0x91
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
154            ucontext structure.
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. */
159         movl    12(%ebp), %ecx
160         movl    %eax, OFFSET_x86_EAX(%ecx)      /* save %eax to VEX */
161         movl    %edx, OFFSET_x86_EDX(%ecx)      /* save %edx to VEX */
162         movl    24(%ebp), %ecx
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
170            already saved. */
171         REBLOCK_SIGNALS
173 4:      /* Now safe from signals. */
174         SIMPLE_RETURN
176 .section .rodata
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
188 .previous
190 /* Prototype:
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):
207         ESTABLISH_STACKFRAME
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. */
212         UNBLOCK_SIGNALS
214         /* Switch to the client stack. */
215         movl    12(%ebp), %edx
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
219            client expects. */
220         movl    OFFSET_x86_EBP(%edx), %ebp      /* %ebp = simulated EBP */
222         /* Put syscall number in %eax. */
223         movl    8+4(%ebx), %eax
225         /* Do the syscall.  Note that the Solaris kernel doesn't directly
226            restart syscalls! */
227         int     $0x91
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. */
253         movl    %ebx, %ebp
254         addl    $4, %ebp
255         REBLOCK_SIGNALS
257 4:      /* Now safe from signals. */
258         SIMPLE_RETURN
260 .section .rodata
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
269 .previous
271 #endif // defined(VGP_x86_solaris)
273 /*--------------------------------------------------------------------*/
274 /*--- end                                                          ---*/
275 /*--------------------------------------------------------------------*/