blob: 0810b5455d1d80aa8ce6df73fd96ea43bb207de9 [file] [log] [blame]
njnc6168192004-11-29 13:54:10 +00001
sewardj0e24d092006-10-17 20:47:13 +00002/*--------------------------------------------------------------------*/
3/*--- Support for doing system calls. syscall-amd64-linux.S ---*/
4/*--------------------------------------------------------------------*/
njnc6168192004-11-29 13:54:10 +00005
6/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
njnc6168192004-11-29 13:54:10 +00009
sewardj0f157dd2013-10-18 14:27:36 +000010 Copyright (C) 2000-2013 Julian Seward
njnc6168192004-11-29 13:54:10 +000011 jseward@acm.org
12
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
28 The GNU General Public License is contained in the file COPYING.
29*/
30
njn8b68b642009-06-24 00:37:09 +000031#if defined(VGP_amd64_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"
sewardj96db5e12005-03-21 17:43:34 +000035#include "libvex_guest_offsets.h"
njnc6168192004-11-29 13:54:10 +000036
njnc6168192004-11-29 13:54:10 +000037
sewardje7aa4ae2005-06-09 12:43:42 +000038/*----------------------------------------------------------------*/
sewardj96db5e12005-03-21 17:43:34 +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 guest_state->guest_RAX. The syscall result
53 is written back to guest_state->guest_RAX on completion.
54
55 Returns 0 if the syscall was successfully called (even if the
56 syscall itself failed), or a -ve error code if one of the
57 sigprocmasks failed (there's no way to determine which one
58 failed).
59
sewardj1b9cd1c2005-06-28 19:04:51 +000060 VG_(fixup_guest_state_after_syscall_interrupted) does the
61 thread state fixup in the case where we were interrupted by a
62 signal.
sewardj96db5e12005-03-21 17:43:34 +000063
64 Prototype:
65
sewardj1b9cd1c2005-06-28 19:04:51 +000066 Int ML_(do_syscall_for_client_WRK(
sewardje7aa4ae2005-06-09 12:43:42 +000067 Int syscallno, // rdi
sewardj96db5e12005-03-21 17:43:34 +000068 void* guest_state, // rsi
69 const vki_sigset_t *sysmask, // rdx
70 const vki_sigset_t *postmask, // rcx
njncda2f0f2009-05-18 02:12:08 +000071 Int sigsetSzB) // r8
sewardj96db5e12005-03-21 17:43:34 +000072
73*/
74
75/* from vki_arch.h */
76#define VKI_SIG_SETMASK 2
77
sewardj1b9cd1c2005-06-28 19:04:51 +000078.globl ML_(do_syscall_for_client_WRK)
79ML_(do_syscall_for_client_WRK):
sewardj96db5e12005-03-21 17:43:34 +000080 /* save callee-saved regs */
81 pushq %rbx
82 pushq %rbp
83 pushq %r12
84 pushq %r13
85 pushq %r14
86 pushq %r15
87
88#define FSZ ((4+1)*4) /* 4 args + ret addr */
89
90#define PUSH_di_si_dx_cx_8 \
91 pushq %rdi ; \
92 pushq %rsi ; \
93 pushq %rdx ; \
94 pushq %rcx ; \
95 pushq %r8
96
97#define POP_di_si_dx_cx_8 \
98 popq %r8 ; \
99 popq %rcx ; \
100 popq %rdx ; \
101 popq %rsi ; \
102 popq %rdi
103
1041: /* Even though we can't take a signal until the sigprocmask completes,
105 start the range early.
106 If eip is in the range [1,2), the syscall hasn't been started yet */
107
108 /* Set the signal mask which should be current during the syscall. */
109 /* Save and restore all 5 arg regs round the call. This is easier
110 than figuring out the minimal set to save/restore. */
111
112 PUSH_di_si_dx_cx_8
113
sewardjf843ad22005-12-27 01:44:33 +0000114 movq $__NR_rt_sigprocmask, %rax // syscall #
115 movq $VKI_SIG_SETMASK, %rdi // how
116 movq %rdx, %rsi // sysmask
117 movq %rcx, %rdx // postmask
njncda2f0f2009-05-18 02:12:08 +0000118 movq %r8, %r10 // sigsetSzB
sewardjf843ad22005-12-27 01:44:33 +0000119 syscall
sewardj96db5e12005-03-21 17:43:34 +0000120
121 POP_di_si_dx_cx_8
122
sewardjf843ad22005-12-27 01:44:33 +0000123 testq %rax, %rax
124 js 7f /* sigprocmask failed */
sewardj96db5e12005-03-21 17:43:34 +0000125
126 /* OK, that worked. Now do the syscall proper. */
127
128 PUSH_di_si_dx_cx_8
129
sewardjf843ad22005-12-27 01:44:33 +0000130 movq %rsi, %rax /* rax --> VexGuestAMD64State * */
131 pushq %rdi /* syscallno -> stack */
132 movq OFFSET_amd64_RDI(%rax), %rdi
133 movq OFFSET_amd64_RSI(%rax), %rsi
134 movq OFFSET_amd64_RDX(%rax), %rdx
135 movq OFFSET_amd64_R10(%rax), %r10
136 movq OFFSET_amd64_R8(%rax), %r8
137 movq OFFSET_amd64_R9(%rax), %r9
138 popq %rax /* syscallno -> %rax */
sewardj96db5e12005-03-21 17:43:34 +0000139
sewardjf843ad22005-12-27 01:44:33 +0000140 /* If rip==2, then the syscall was either just about
141 to start, or was interrupted and the kernel was
142 restarting it. */
1432: syscall
1443: /* In the range [3, 4), the syscall result is in %rax,
145 but hasn't been committed to RAX. */
sewardj96db5e12005-03-21 17:43:34 +0000146
147 POP_di_si_dx_cx_8
148
149 movq %rax, OFFSET_amd64_RAX(%rsi) /* save back to RAX */
150
sewardjf843ad22005-12-27 01:44:33 +00001514: /* Re-block signals. If eip is in [4,5), then the syscall
152 is complete and we needn't worry about it. */
153
sewardj96db5e12005-03-21 17:43:34 +0000154 PUSH_di_si_dx_cx_8
155
sewardjf843ad22005-12-27 01:44:33 +0000156 movq $__NR_rt_sigprocmask, %rax // syscall #
157 movq $VKI_SIG_SETMASK, %rdi // how
158 movq %rcx, %rsi // postmask
159 xorq %rdx, %rdx // NULL
njncda2f0f2009-05-18 02:12:08 +0000160 movq %r8, %r10 // sigsetSzB
sewardjf843ad22005-12-27 01:44:33 +0000161 syscall
sewardj96db5e12005-03-21 17:43:34 +0000162
163 POP_di_si_dx_cx_8
164
sewardjf843ad22005-12-27 01:44:33 +0000165 testq %rax, %rax
166 js 7f /* sigprocmask failed */
167
sewardj96db5e12005-03-21 17:43:34 +00001685: /* now safe from signals */
sewardjf843ad22005-12-27 01:44:33 +0000169 movq $0, %rax /* SUCCESS */
sewardj96db5e12005-03-21 17:43:34 +0000170 popq %r15
171 popq %r14
172 popq %r13
173 popq %r12
174 popq %rbp
175 popq %rbx
sewardj96db5e12005-03-21 17:43:34 +0000176 ret
177
sewardjf843ad22005-12-27 01:44:33 +00001787: /* failure: return 0x8000 | error code */
179 negq %rax
180 andq $0x7FFF, %rax
181 orq $0x8000, %rax
182 popq %r15
183 popq %r14
184 popq %r13
185 popq %r12
186 popq %rbp
187 popq %rbx
188 ret
189#undef FSZ
190
sewardj96db5e12005-03-21 17:43:34 +0000191.section .rodata
sewardj1b9cd1c2005-06-28 19:04:51 +0000192/* export the ranges so that
193 VG_(fixup_guest_state_after_syscall_interrupted) can do the
194 right thing */
sewardj96db5e12005-03-21 17:43:34 +0000195
sewardj1b9cd1c2005-06-28 19:04:51 +0000196.globl ML_(blksys_setup)
197.globl ML_(blksys_restart)
198.globl ML_(blksys_complete)
199.globl ML_(blksys_committed)
200.globl ML_(blksys_finished)
201ML_(blksys_setup): .quad 1b
202ML_(blksys_restart): .quad 2b
203ML_(blksys_complete): .quad 3b
204ML_(blksys_committed): .quad 4b
205ML_(blksys_finished): .quad 5b
sewardj96db5e12005-03-21 17:43:34 +0000206.previous
207
njnc6168192004-11-29 13:54:10 +0000208/* Let the linker know we don't need an executable stack */
209.section .note.GNU-stack,"",@progbits
210
njn8b68b642009-06-24 00:37:09 +0000211#endif // defined(VGP_amd64_linux)
212
sewardj0e24d092006-10-17 20:47:13 +0000213/*--------------------------------------------------------------------*/
214/*--- end ---*/
215/*--------------------------------------------------------------------*/