blob: 533fb0eea1b16291e6594257d2496105c3f409db [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
Elliott Hughesed398002017-06-21 14:41:24 -070010 Copyright (C) 2000-2017 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
florian3f1d6132015-09-30 20:30:48 +000031#include "pub_core_basics_asm.h"
32
njn8b68b642009-06-24 00:37:09 +000033#if defined(VGP_x86_linux)
34
njn1a1e95c2009-06-03 06:50:06 +000035#include "pub_core_vkiscnums_asm.h"
sewardjb5f6f512005-03-10 23:59:00 +000036#include "libvex_guest_offsets.h"
37
sewardjb5f6f512005-03-10 23:59:00 +000038
sewardje7aa4ae2005-06-09 12:43:42 +000039/*----------------------------------------------------------------*/
sewardjb5f6f512005-03-10 23:59:00 +000040/*
41 Perform a syscall for the client. This will run a syscall
42 with the client's specific per-thread signal mask.
43
44 The structure of this function is such that, if the syscall is
45 interrupted by a signal, we can determine exactly what
46 execution state we were in with respect to the execution of
47 the syscall by examining the value of %eip in the signal
48 handler. This means that we can always do the appropriate
49 thing to precisely emulate the kernel's signal/syscall
50 interactions.
51
52 The syscall number is taken from the argument, even though it
53 should also be in regs->m_eax. The syscall result is written
54 back to regs->m_eax on completion.
55
56 Returns 0 if the syscall was successfully called (even if the
sewardj39e81602005-12-22 20:16:00 +000057 syscall itself failed), or a nonzero error code in the lowest
58 8 bits if one of the sigprocmasks failed (there's no way to
59 determine which one failed). And there's no obvious way to
60 recover from that either, but nevertheless we want to know.
sewardjb5f6f512005-03-10 23:59:00 +000061
sewardj1b9cd1c2005-06-28 19:04:51 +000062 VG_(fixup_guest_state_after_syscall_interrupted) does the
63 thread state fixup in the case where we were interrupted by a
64 signal.
sewardjb5f6f512005-03-10 23:59:00 +000065
66 Prototype:
67
sewardj39e81602005-12-22 20:16:00 +000068 UWord ML_(do_syscall_for_client_WRK)(
sewardja8d8e232005-06-07 20:04:56 +000069 Int syscallno, // 0
sewardjb5f6f512005-03-10 23:59:00 +000070 void* guest_state, // 4
71 const vki_sigset_t *sysmask, // 8
72 const vki_sigset_t *postmask, // 12
njncda2f0f2009-05-18 02:12:08 +000073 Int sigsetSzB) // 16
sewardjb5f6f512005-03-10 23:59:00 +000074
75*/
76
77/* from vki_arch.h */
78#define VKI_SIG_SETMASK 2
79
sewardj1b9cd1c2005-06-28 19:04:51 +000080.globl ML_(do_syscall_for_client_WRK)
81ML_(do_syscall_for_client_WRK):
philippe2d616332015-05-17 08:24:40 +000082 .cfi_startproc
sewardjb5f6f512005-03-10 23:59:00 +000083 /* save callee-saved regs */
84 push %esi
philippe2d616332015-05-17 08:24:40 +000085 .cfi_adjust_cfa_offset 4
86 .cfi_offset %esi, -8
sewardjb5f6f512005-03-10 23:59:00 +000087 push %edi
philippe2d616332015-05-17 08:24:40 +000088 .cfi_adjust_cfa_offset 4
89 .cfi_offset %esi, -12
sewardjb5f6f512005-03-10 23:59:00 +000090 push %ebx
philippe2d616332015-05-17 08:24:40 +000091 .cfi_adjust_cfa_offset 4
92 .cfi_offset %esi, -16
sewardjb5f6f512005-03-10 23:59:00 +000093 push %ebp
philippe2d616332015-05-17 08:24:40 +000094 .cfi_adjust_cfa_offset 4
95 .cfi_offset %esi, -20
sewardjb5f6f512005-03-10 23:59:00 +000096#define FSZ ((4+1)*4) /* 4 args + ret addr */
97
981: /* Even though we can't take a signal until the sigprocmask completes,
99 start the range early.
100 If eip is in the range [1,2), the syscall hasn't been started yet */
101
102 /* Set the signal mask which should be current during the syscall. */
sewardjcfdc5fd2007-08-24 20:37:09 +0000103 movl $ __NR_rt_sigprocmask, %eax
104 movl $ VKI_SIG_SETMASK, %ebx
sewardjb5f6f512005-03-10 23:59:00 +0000105 movl 8+FSZ(%esp), %ecx
106 movl 12+FSZ(%esp), %edx
107 movl 16+FSZ(%esp), %esi
108 int $0x80
109 testl %eax, %eax
sewardj39e81602005-12-22 20:16:00 +0000110 js 7f /* sigprocmask failed */
sewardjb5f6f512005-03-10 23:59:00 +0000111
112 movl 4+FSZ(%esp), %eax /* eax == ThreadState * */
113
114 movl OFFSET_x86_EBX(%eax), %ebx
115 movl OFFSET_x86_ECX(%eax), %ecx
116 movl OFFSET_x86_EDX(%eax), %edx
117 movl OFFSET_x86_ESI(%eax), %esi
118 movl OFFSET_x86_EDI(%eax), %edi
119 movl OFFSET_x86_EBP(%eax), %ebp
120 movl 0+FSZ(%esp), %eax /* use syscallno argument rather than thread EAX */
121
122 /* If eip==2, then the syscall was either just about to start,
123 or was interrupted and the kernel was restarting it. */
1242: int $0x80
1253: /* In the range [3, 4), the syscall result is in %eax, but hasn't been
126 committed to EAX. */
127 movl 4+FSZ(%esp), %ebx
128 movl %eax, OFFSET_x86_EAX(%ebx) /* save back to EAX */
129
1304: /* Re-block signals. If eip is in [4,5), then the syscall is complete and
131 we needn't worry about it. */
sewardjcfdc5fd2007-08-24 20:37:09 +0000132 movl $ __NR_rt_sigprocmask, %eax
133 movl $ VKI_SIG_SETMASK, %ebx
sewardjb5f6f512005-03-10 23:59:00 +0000134 movl 12+FSZ(%esp), %ecx
135 xorl %edx, %edx
136 movl 16+FSZ(%esp), %esi
137 int $0x80
sewardj39e81602005-12-22 20:16:00 +0000138 testl %eax, %eax
139 js 7f /* sigprocmask failed */
sewardjb5f6f512005-03-10 23:59:00 +0000140
1415: /* now safe from signals */
sewardj39e81602005-12-22 20:16:00 +0000142 movl $0, %eax /* SUCCESS */
sewardjb5f6f512005-03-10 23:59:00 +0000143 popl %ebp
philippe2d616332015-05-17 08:24:40 +0000144 .cfi_adjust_cfa_offset -4
sewardjb5f6f512005-03-10 23:59:00 +0000145 popl %ebx
philippe2d616332015-05-17 08:24:40 +0000146 .cfi_adjust_cfa_offset -4
sewardjb5f6f512005-03-10 23:59:00 +0000147 popl %edi
philippe2d616332015-05-17 08:24:40 +0000148 .cfi_adjust_cfa_offset -4
sewardjb5f6f512005-03-10 23:59:00 +0000149 popl %esi
philippe2d616332015-05-17 08:24:40 +0000150 .cfi_adjust_cfa_offset -4
sewardjb5f6f512005-03-10 23:59:00 +0000151 ret
philippe2d616332015-05-17 08:24:40 +0000152 .cfi_adjust_cfa_offset 4*4
sewardjb5f6f512005-03-10 23:59:00 +0000153
sewardj39e81602005-12-22 20:16:00 +00001547: /* failure: return 0x8000 | error code */
155 negl %eax
156 andl $0x7FFF, %eax
157 orl $0x8000, %eax
158 popl %ebp
philippe2d616332015-05-17 08:24:40 +0000159 .cfi_adjust_cfa_offset -4
sewardj39e81602005-12-22 20:16:00 +0000160 popl %ebx
philippe2d616332015-05-17 08:24:40 +0000161 .cfi_adjust_cfa_offset -4
sewardj39e81602005-12-22 20:16:00 +0000162 popl %edi
philippe2d616332015-05-17 08:24:40 +0000163 .cfi_adjust_cfa_offset -4
sewardj39e81602005-12-22 20:16:00 +0000164 popl %esi
philippe2d616332015-05-17 08:24:40 +0000165 .cfi_adjust_cfa_offset -4
sewardj39e81602005-12-22 20:16:00 +0000166 ret
philippe2d616332015-05-17 08:24:40 +0000167 .cfi_endproc
sewardj39e81602005-12-22 20:16:00 +0000168#undef FSZ
169
170
sewardjb5f6f512005-03-10 23:59:00 +0000171.section .rodata
sewardja8d8e232005-06-07 20:04:56 +0000172/* export the ranges so that
173 VG_(fixup_guest_state_after_syscall_interrupted) can do the
174 right thing */
sewardjb5f6f512005-03-10 23:59:00 +0000175
sewardj1b9cd1c2005-06-28 19:04:51 +0000176.globl ML_(blksys_setup)
177.globl ML_(blksys_restart)
178.globl ML_(blksys_complete)
179.globl ML_(blksys_committed)
180.globl ML_(blksys_finished)
181ML_(blksys_setup): .long 1b
182ML_(blksys_restart): .long 2b
183ML_(blksys_complete): .long 3b
184ML_(blksys_committed): .long 4b
185ML_(blksys_finished): .long 5b
sewardjb5f6f512005-03-10 23:59:00 +0000186.previous
thughes4ad52d02004-06-27 17:37:21 +0000187
njn8b68b642009-06-24 00:37:09 +0000188#endif // defined(VGP_x86_linux)
189
florian3f1d6132015-09-30 20:30:48 +0000190/* Let the linker know we don't need an executable stack */
191MARK_STACK_NO_EXEC
192
sewardj39e81602005-12-22 20:16:00 +0000193/*--------------------------------------------------------------------*/
194/*--- end ---*/
195/*--------------------------------------------------------------------*/