blob: 78b3df41fe2ecd3cc312766719591bc36ecb566c [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
sewardj39e81602005-12-22 20:16:00 +00002/*--------------------------------------------------------------------*/
3/*--- Support for doing system calls. syscall-x86-linux.S ---*/
4/*--------------------------------------------------------------------*/
sewardjde4a1d02002-03-22 01:27:54 +00005
6/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjde4a1d02002-03-22 01:27:54 +00009
sewardj0f157dd2013-10-18 14:27:36 +000010 Copyright (C) 2000-2013 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +000012
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
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
njn8b68b642009-06-24 00:37:09 +000031#if defined(VGP_x86_linux)
32
sewardj45f4e7c2005-09-27 19:20:21 +000033#include "pub_core_basics_asm.h"
njn1a1e95c2009-06-03 06:50:06 +000034#include "pub_core_vkiscnums_asm.h"
sewardjb5f6f512005-03-10 23:59:00 +000035#include "libvex_guest_offsets.h"
36
sewardjb5f6f512005-03-10 23:59:00 +000037
sewardje7aa4ae2005-06-09 12:43:42 +000038/*----------------------------------------------------------------*/
sewardjb5f6f512005-03-10 23:59:00 +000039/*
40 Perform a syscall for the client. This will run a syscall
41 with the client's specific per-thread signal mask.
42
43 The structure of this function is such that, if the syscall is
44 interrupted by a signal, we can determine exactly what
45 execution state we were in with respect to the execution of
46 the syscall by examining the value of %eip in the signal
47 handler. This means that we can always do the appropriate
48 thing to precisely emulate the kernel's signal/syscall
49 interactions.
50
51 The syscall number is taken from the argument, even though it
52 should also be in regs->m_eax. The syscall result is written
53 back to regs->m_eax on completion.
54
55 Returns 0 if the syscall was successfully called (even if the
sewardj39e81602005-12-22 20:16:00 +000056 syscall itself failed), or a nonzero error code in the lowest
57 8 bits if one of the sigprocmasks failed (there's no way to
58 determine which one failed). And there's no obvious way to
59 recover from that either, but nevertheless we want to know.
sewardjb5f6f512005-03-10 23:59:00 +000060
sewardj1b9cd1c2005-06-28 19:04:51 +000061 VG_(fixup_guest_state_after_syscall_interrupted) does the
62 thread state fixup in the case where we were interrupted by a
63 signal.
sewardjb5f6f512005-03-10 23:59:00 +000064
65 Prototype:
66
sewardj39e81602005-12-22 20:16:00 +000067 UWord ML_(do_syscall_for_client_WRK)(
sewardja8d8e232005-06-07 20:04:56 +000068 Int syscallno, // 0
sewardjb5f6f512005-03-10 23:59:00 +000069 void* guest_state, // 4
70 const vki_sigset_t *sysmask, // 8
71 const vki_sigset_t *postmask, // 12
njncda2f0f2009-05-18 02:12:08 +000072 Int sigsetSzB) // 16
sewardjb5f6f512005-03-10 23:59:00 +000073
74*/
75
76/* from vki_arch.h */
77#define VKI_SIG_SETMASK 2
78
sewardj1b9cd1c2005-06-28 19:04:51 +000079.globl ML_(do_syscall_for_client_WRK)
80ML_(do_syscall_for_client_WRK):
sewardjb5f6f512005-03-10 23:59:00 +000081 /* save callee-saved regs */
82 push %esi
83 push %edi
84 push %ebx
85 push %ebp
86#define FSZ ((4+1)*4) /* 4 args + ret addr */
87
881: /* Even though we can't take a signal until the sigprocmask completes,
89 start the range early.
90 If eip is in the range [1,2), the syscall hasn't been started yet */
91
92 /* Set the signal mask which should be current during the syscall. */
sewardjcfdc5fd2007-08-24 20:37:09 +000093 movl $ __NR_rt_sigprocmask, %eax
94 movl $ VKI_SIG_SETMASK, %ebx
sewardjb5f6f512005-03-10 23:59:00 +000095 movl 8+FSZ(%esp), %ecx
96 movl 12+FSZ(%esp), %edx
97 movl 16+FSZ(%esp), %esi
98 int $0x80
99 testl %eax, %eax
sewardj39e81602005-12-22 20:16:00 +0000100 js 7f /* sigprocmask failed */
sewardjb5f6f512005-03-10 23:59:00 +0000101
102 movl 4+FSZ(%esp), %eax /* eax == ThreadState * */
103
104 movl OFFSET_x86_EBX(%eax), %ebx
105 movl OFFSET_x86_ECX(%eax), %ecx
106 movl OFFSET_x86_EDX(%eax), %edx
107 movl OFFSET_x86_ESI(%eax), %esi
108 movl OFFSET_x86_EDI(%eax), %edi
109 movl OFFSET_x86_EBP(%eax), %ebp
110 movl 0+FSZ(%esp), %eax /* use syscallno argument rather than thread EAX */
111
112 /* If eip==2, then the syscall was either just about to start,
113 or was interrupted and the kernel was restarting it. */
1142: int $0x80
1153: /* In the range [3, 4), the syscall result is in %eax, but hasn't been
116 committed to EAX. */
117 movl 4+FSZ(%esp), %ebx
118 movl %eax, OFFSET_x86_EAX(%ebx) /* save back to EAX */
119
1204: /* Re-block signals. If eip is in [4,5), then the syscall is complete and
121 we needn't worry about it. */
sewardjcfdc5fd2007-08-24 20:37:09 +0000122 movl $ __NR_rt_sigprocmask, %eax
123 movl $ VKI_SIG_SETMASK, %ebx
sewardjb5f6f512005-03-10 23:59:00 +0000124 movl 12+FSZ(%esp), %ecx
125 xorl %edx, %edx
126 movl 16+FSZ(%esp), %esi
127 int $0x80
sewardj39e81602005-12-22 20:16:00 +0000128 testl %eax, %eax
129 js 7f /* sigprocmask failed */
sewardjb5f6f512005-03-10 23:59:00 +0000130
1315: /* now safe from signals */
sewardj39e81602005-12-22 20:16:00 +0000132 movl $0, %eax /* SUCCESS */
sewardjb5f6f512005-03-10 23:59:00 +0000133 popl %ebp
134 popl %ebx
135 popl %edi
136 popl %esi
sewardjb5f6f512005-03-10 23:59:00 +0000137 ret
138
sewardj39e81602005-12-22 20:16:00 +00001397: /* failure: return 0x8000 | error code */
140 negl %eax
141 andl $0x7FFF, %eax
142 orl $0x8000, %eax
143 popl %ebp
144 popl %ebx
145 popl %edi
146 popl %esi
147 ret
148#undef FSZ
149
150
sewardjb5f6f512005-03-10 23:59:00 +0000151.section .rodata
sewardja8d8e232005-06-07 20:04:56 +0000152/* export the ranges so that
153 VG_(fixup_guest_state_after_syscall_interrupted) can do the
154 right thing */
sewardjb5f6f512005-03-10 23:59:00 +0000155
sewardj1b9cd1c2005-06-28 19:04:51 +0000156.globl ML_(blksys_setup)
157.globl ML_(blksys_restart)
158.globl ML_(blksys_complete)
159.globl ML_(blksys_committed)
160.globl ML_(blksys_finished)
161ML_(blksys_setup): .long 1b
162ML_(blksys_restart): .long 2b
163ML_(blksys_complete): .long 3b
164ML_(blksys_committed): .long 4b
165ML_(blksys_finished): .long 5b
sewardjb5f6f512005-03-10 23:59:00 +0000166.previous
167
thughes4ad52d02004-06-27 17:37:21 +0000168/* Let the linker know we don't need an executable stack */
169.section .note.GNU-stack,"",@progbits
170
njn8b68b642009-06-24 00:37:09 +0000171#endif // defined(VGP_x86_linux)
172
sewardj39e81602005-12-22 20:16:00 +0000173/*--------------------------------------------------------------------*/
174/*--- end ---*/
175/*--------------------------------------------------------------------*/