Add DRD suppression patterns for races triggered by std::ostream
[valgrind.git] / coregrind / m_syswrap / syscall-x86-solaris.S
blob019401cf22c591e650826dc13ed322e10e6ac9bb
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-2017 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 #include "pub_core_basics_asm.h"
33 #if defined(VGP_x86_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
41 /* Prototype:
42    Int ML_(do_syscall_for_client_WRK)(
43       Int syscallno,                    // %ebp+8
44       void *guest_state,                // %ebp+12
45       const vki_sigset_t *sysmask,      // %ebp+16
46       const vki_sigset_t *postmask,     // %ebp+20
47       UChar *cflag)                     // %ebp+24
50 .macro ESTABLISH_STACKFRAME
51         /* Establish stack frame. */
52         pushl   %ebp
53         movl    %esp, %ebp
54         pushl   %ebx                            /* save %ebx */
56         /* We'll use %ebx instead of %ebp to address the stack frame after the
57            door syscall is finished because %ebp is cleared by the syscall. */
58         movl    %esp, %ebx                      /* %ebx = %ebp - 4 */
59 .endm
61 .macro UNBLOCK_SIGNALS
62         /* Set the signal mask which should be current during the syscall. */
63         /* Set up for sigprocmask(SIG_SETMASK, sysmask, postmask). */
64         pushl   20(%ebp)
65         pushl   16(%ebp)
66         pushl   $VKI_SIG_SETMASK
67         pushl   $0xcafebabe                     /* totally fake return address */
68         movl    $__NR_sigprocmask, %eax
69         int     $0x91
70         jc      sigprocmask_failed              /* sigprocmask failed */
71         addl    $16, %esp
72 .endm
74 .macro REBLOCK_SIGNALS
75         /* Set up for sigprocmask(SIG_SETMASK, postmask, NULL). */
76         pushl   $0
77         pushl   20(%ebp)
78         pushl   $VKI_SIG_SETMASK
79         pushl   $0xcafef00d                     /* totally fake return address */
80         movl    $__NR_sigprocmask, %eax
81         int     $0x91
82         /* The syscall above changes the carry flag.  This means that if the
83            syscall fails and we receive an interrupt after it then we've got
84            an invalid carry flag value in the fixup code.  We don't care about
85            it because this syscall should never fail and if it does then we're
86            going to stop Valgrind anyway. */
87         jc      sigprocmask_failed              /* sigprocmask failed */
88         addl    $16, %esp
89 .endm
91 .macro SIMPLE_RETURN
92         xorl    %eax, %eax                      /* SUCCESS */
93         movl    -4(%ebp), %ebx                  /* restore %ebx */
94         movl    %ebp, %esp
95         popl    %ebp
96         ret
97 .endm
99 sigprocmask_failed:
100         /* Failure: return 0x8000 | error code. */
101         /* Note that we enter here with %esp being 16 too low (4 extra words
102            on the stack).  But because we're nuking the stack frame now, that
103            doesn't matter. */
104         andl    $0x7FFF, %eax
105         orl     $0x8000, %eax
106         movl    -4(%ebp), %ebx                  /* restore %ebx */
107         movl    %ebp, %esp
108         popl    %ebp
109         ret
111 .globl ML_(do_syscall_for_client_WRK)
112 ML_(do_syscall_for_client_WRK):
113         ESTABLISH_STACKFRAME
115 1:      /* Even though we can't take a signal until the sigprocmask completes,
116            start the range early.  If %eip is in the range [1, 2), the syscall
117            hasn't been started yet. */
118         UNBLOCK_SIGNALS
120         /* Copy syscall parameters to the stack - assume no more than 8 plus
121            the return address. */
122         /* do_syscall8 */
123         movl    12(%ebp), %edx
124         movl    OFFSET_x86_ESP(%edx), %edx      /* %edx = simulated ESP */
125         movl    28+4(%edx), %eax
126         pushl   %eax
127         movl    24+4(%edx), %eax
128         pushl   %eax
129         movl    20+4(%edx), %eax
130         pushl   %eax
131         movl    16+4(%edx), %eax
132         pushl   %eax
133         movl    12+4(%edx), %eax
134         pushl   %eax
135         movl    8+4(%edx), %eax
136         pushl   %eax
137         movl    4+4(%edx), %eax
138         pushl   %eax
139         movl    0+4(%edx), %eax
140         pushl   %eax
141         /* Return address. */
142         movl    0(%edx), %eax
143         pushl   %eax
145         /* Put syscall number in %eax. */
146         movl    8(%ebp), %eax
148         /* Do the syscall.  Note that the Solaris kernel doesn't directly
149            restart syscalls! */
150         int     $0x91
152 2:      /* In the range [2, 3), the syscall result is in %eax and %edx and C,
153            but hasn't been committed to the thread state.  If we get
154            interrupted in this section then we'll just use values saved in the
155            ucontext structure.
157            Important note for this and the following section: Don't add here
158            any code that alters the carry flag or worse, call any function.
159            That would completely break the fixup after an interrupt. */
160         movl    12(%ebp), %ecx
161         movl    %eax, OFFSET_x86_EAX(%ecx)      /* save %eax to VEX */
162         movl    %edx, OFFSET_x86_EDX(%ecx)      /* save %edx to VEX */
163         movl    24(%ebp), %ecx
164         setc    0(%ecx)                         /* save returned carry flag */
166 3:      /* Re-block signals. If %eip is in [3, 4), then the syscall is
167            complete and we do not need to worry about it.  We have to only
168            correctly save the carry flag.  If we get interrupted in this
169            section then we just have to propagate the carry flag from the
170            ucontext structure to the thread state, %eax and %edx values are
171            already saved. */
172         REBLOCK_SIGNALS
174 4:      /* Now safe from signals. */
175         SIMPLE_RETURN
177 .section .rodata
178 /* Export the ranges so that
179    VG_(fixup_guest_state_after_syscall_interrupted) can do the right thing. */
181 .globl ML_(blksys_setup)
182 .globl ML_(blksys_complete)
183 .globl ML_(blksys_committed)
184 .globl ML_(blksys_finished)
185 ML_(blksys_setup):      .long 1b
186 ML_(blksys_complete):   .long 2b
187 ML_(blksys_committed):  .long 3b
188 ML_(blksys_finished):   .long 4b
189 .previous
191 /* Prototype:
192    Int ML_(do_syscall_for_client_dret_WRK)(
193       Int syscallno,                    // %ebp+8 = %ebx+8+4
194       void *guest_state,                // %ebp+12 = %ebx+12+4
195       const vki_sigset_t *sysmask,      // %ebp+16 = %ebx+16+4
196       const vki_sigset_t *postmask,     // %ebp+20 = %ebx+20+4
197       UChar *cflag)                     // %ebp+24 = %ebx+24+4
200 /* Door_return is a very special call because the data are stored by the
201    kernel directly on the stack and the stack pointer is appropriately
202    modified by the kernel.  Therefore we switch to the client stack before
203    doing the syscall, this is relatively trivial but an extra care has to be
204    taken when we get interrupted at some point. */
206 .globl ML_(do_syscall_for_client_dret_WRK)
207 ML_(do_syscall_for_client_dret_WRK):
208         ESTABLISH_STACKFRAME
210 1:      /* Even though we can't take a signal until the sigprocmask completes,
211            start the range early.  If %eip is in the range [1, 2), the syscall
212            hasn't been started yet. */
213         UNBLOCK_SIGNALS
215         /* Switch to the client stack. */
216         movl    12(%ebp), %edx
217         movl    OFFSET_x86_ESP(%edx), %esp      /* %esp = simulated ESP */
218         /* Change %ebp to a client value. It will always get committed by
219            the fixup code for range [2, 3) so it needs to be set to what the
220            client expects. */
221         movl    OFFSET_x86_EBP(%edx), %ebp      /* %ebp = simulated EBP */
223         /* Put syscall number in %eax. */
224         movl    8+4(%ebx), %eax
226         /* Do the syscall.  Note that the Solaris kernel doesn't directly
227            restart syscalls! */
228         int     $0x91
230 2:      /* In the range [2, 3), the syscall result is in %eax, %edx, %esp and
231            %ebp and C, but hasn't been committed to the thread state.  If we
232            get interrupted in this section then we'll just use values saved in
233            the ucontext structure.
235            Important note for this and the following section: Don't add here
236            any code that alters the carry flag or worse, call any function.
237            That would completely break the fixup after an interrupt. */
238         movl    12+4(%ebx), %ecx
239         movl    %eax, OFFSET_x86_EAX(%ecx)      /* save %eax to VEX */
240         movl    %edx, OFFSET_x86_EDX(%ecx)      /* save %edx to VEX */
241         movl    %esp, OFFSET_x86_ESP(%ecx)      /* save %esp to VEX */
242         movl    %ebp, OFFSET_x86_EBP(%ecx)      /* save %ebp to VEX */
243         movl    24+4(%ebx), %ecx
244         setc    0(%ecx)                         /* save returned carry flag */
246         movl    %ebx, %esp                      /* switch to V stack */
248 3:      /* Re-block signals. If %eip is in [3, 4), then the syscall is
249            complete and we do not need worry about it.  We have to only
250            correctly save the carry flag.  If we get interrupted in this
251            section then we just have to propagate the carry flag from the
252            ucontext structure to the thread state, %eax, %edx, %esp and %ebp
253            values are already saved. */
254         movl    %ebx, %ebp
255         addl    $4, %ebp
256         REBLOCK_SIGNALS
258 4:      /* Now safe from signals. */
259         SIMPLE_RETURN
261 .section .rodata
262 .globl ML_(blksys_setup_DRET)
263 .globl ML_(blksys_complete_DRET)
264 .globl ML_(blksys_committed_DRET)
265 .globl ML_(blksys_finished_DRET)
266 ML_(blksys_setup_DRET):         .long 1b
267 ML_(blksys_complete_DRET):      .long 2b
268 ML_(blksys_committed_DRET):     .long 3b
269 ML_(blksys_finished_DRET):      .long 4b
270 .previous
272 #endif // defined(VGP_x86_solaris)
274 /* Let the linker know we don't need an executable stack */
275 MARK_STACK_NO_EXEC
277 /*--------------------------------------------------------------------*/
278 /*--- end                                                          ---*/
279 /*--------------------------------------------------------------------*/