blob: 7432edbd8a41c7fac87a0a97f15ea741bc72101f [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
sewardje4b0bf02006-06-05 23:21:15 +000010 Copyright (C) 2000-2006 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
sewardj45f4e7c2005-09-27 19:20:21 +000031#include "pub_core_basics_asm.h"
sewardj4eee4762006-10-14 15:51:32 +000032#include "pub_core_vkiscnums.h"
sewardjb5f6f512005-03-10 23:59:00 +000033#include "libvex_guest_offsets.h"
34
sewardjb5f6f512005-03-10 23:59:00 +000035
sewardje7aa4ae2005-06-09 12:43:42 +000036/*----------------------------------------------------------------*/
sewardjb5f6f512005-03-10 23:59:00 +000037/*
38 Perform a syscall for the client. This will run a syscall
39 with the client's specific per-thread signal mask.
40
41 The structure of this function is such that, if the syscall is
42 interrupted by a signal, we can determine exactly what
43 execution state we were in with respect to the execution of
44 the syscall by examining the value of %eip in the signal
45 handler. This means that we can always do the appropriate
46 thing to precisely emulate the kernel's signal/syscall
47 interactions.
48
49 The syscall number is taken from the argument, even though it
50 should also be in regs->m_eax. The syscall result is written
51 back to regs->m_eax on completion.
52
53 Returns 0 if the syscall was successfully called (even if the
sewardj39e81602005-12-22 20:16:00 +000054 syscall itself failed), or a nonzero error code in the lowest
55 8 bits if one of the sigprocmasks failed (there's no way to
56 determine which one failed). And there's no obvious way to
57 recover from that either, but nevertheless we want to know.
sewardjb5f6f512005-03-10 23:59:00 +000058
sewardj1b9cd1c2005-06-28 19:04:51 +000059 VG_(fixup_guest_state_after_syscall_interrupted) does the
60 thread state fixup in the case where we were interrupted by a
61 signal.
sewardjb5f6f512005-03-10 23:59:00 +000062
63 Prototype:
64
sewardj39e81602005-12-22 20:16:00 +000065 UWord ML_(do_syscall_for_client_WRK)(
sewardja8d8e232005-06-07 20:04:56 +000066 Int syscallno, // 0
sewardjb5f6f512005-03-10 23:59:00 +000067 void* guest_state, // 4
68 const vki_sigset_t *sysmask, // 8
69 const vki_sigset_t *postmask, // 12
70 Int nsigwords) // 16
71
72*/
73
74/* from vki_arch.h */
75#define VKI_SIG_SETMASK 2
76
sewardj1b9cd1c2005-06-28 19:04:51 +000077.globl ML_(do_syscall_for_client_WRK)
78ML_(do_syscall_for_client_WRK):
sewardjb5f6f512005-03-10 23:59:00 +000079 /* save callee-saved regs */
80 push %esi
81 push %edi
82 push %ebx
83 push %ebp
84#define FSZ ((4+1)*4) /* 4 args + ret addr */
85
861: /* Even though we can't take a signal until the sigprocmask completes,
87 start the range early.
88 If eip is in the range [1,2), the syscall hasn't been started yet */
89
90 /* Set the signal mask which should be current during the syscall. */
91 movl $__NR_rt_sigprocmask, %eax
92 movl $VKI_SIG_SETMASK, %ebx
93 movl 8+FSZ(%esp), %ecx
94 movl 12+FSZ(%esp), %edx
95 movl 16+FSZ(%esp), %esi
96 int $0x80
97 testl %eax, %eax
sewardj39e81602005-12-22 20:16:00 +000098 js 7f /* sigprocmask failed */
sewardjb5f6f512005-03-10 23:59:00 +000099
100 movl 4+FSZ(%esp), %eax /* eax == ThreadState * */
101
102 movl OFFSET_x86_EBX(%eax), %ebx
103 movl OFFSET_x86_ECX(%eax), %ecx
104 movl OFFSET_x86_EDX(%eax), %edx
105 movl OFFSET_x86_ESI(%eax), %esi
106 movl OFFSET_x86_EDI(%eax), %edi
107 movl OFFSET_x86_EBP(%eax), %ebp
108 movl 0+FSZ(%esp), %eax /* use syscallno argument rather than thread EAX */
109
110 /* If eip==2, then the syscall was either just about to start,
111 or was interrupted and the kernel was restarting it. */
1122: int $0x80
1133: /* In the range [3, 4), the syscall result is in %eax, but hasn't been
114 committed to EAX. */
115 movl 4+FSZ(%esp), %ebx
116 movl %eax, OFFSET_x86_EAX(%ebx) /* save back to EAX */
117
1184: /* Re-block signals. If eip is in [4,5), then the syscall is complete and
119 we needn't worry about it. */
120 movl $__NR_rt_sigprocmask, %eax
121 movl $VKI_SIG_SETMASK, %ebx
122 movl 12+FSZ(%esp), %ecx
123 xorl %edx, %edx
124 movl 16+FSZ(%esp), %esi
125 int $0x80
sewardj39e81602005-12-22 20:16:00 +0000126 testl %eax, %eax
127 js 7f /* sigprocmask failed */
sewardjb5f6f512005-03-10 23:59:00 +0000128
1295: /* now safe from signals */
sewardj39e81602005-12-22 20:16:00 +0000130 movl $0, %eax /* SUCCESS */
sewardjb5f6f512005-03-10 23:59:00 +0000131 popl %ebp
132 popl %ebx
133 popl %edi
134 popl %esi
sewardjb5f6f512005-03-10 23:59:00 +0000135 ret
136
sewardj39e81602005-12-22 20:16:00 +00001377: /* failure: return 0x8000 | error code */
138 negl %eax
139 andl $0x7FFF, %eax
140 orl $0x8000, %eax
141 popl %ebp
142 popl %ebx
143 popl %edi
144 popl %esi
145 ret
146#undef FSZ
147
148
sewardjb5f6f512005-03-10 23:59:00 +0000149.section .rodata
sewardja8d8e232005-06-07 20:04:56 +0000150/* export the ranges so that
151 VG_(fixup_guest_state_after_syscall_interrupted) can do the
152 right thing */
sewardjb5f6f512005-03-10 23:59:00 +0000153
sewardj1b9cd1c2005-06-28 19:04:51 +0000154.globl ML_(blksys_setup)
155.globl ML_(blksys_restart)
156.globl ML_(blksys_complete)
157.globl ML_(blksys_committed)
158.globl ML_(blksys_finished)
159ML_(blksys_setup): .long 1b
160ML_(blksys_restart): .long 2b
161ML_(blksys_complete): .long 3b
162ML_(blksys_committed): .long 4b
163ML_(blksys_finished): .long 5b
sewardjb5f6f512005-03-10 23:59:00 +0000164.previous
165
thughes4ad52d02004-06-27 17:37:21 +0000166/* Let the linker know we don't need an executable stack */
167.section .note.GNU-stack,"",@progbits
168
sewardj39e81602005-12-22 20:16:00 +0000169/*--------------------------------------------------------------------*/
170/*--- end ---*/
171/*--------------------------------------------------------------------*/