blob: e2eb77f8d7a3d06c3122bd2a2c88700a0f9304d9 [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
Elliott Hughesed398002017-06-21 14:41:24 -070010 Copyright (C) 2000-2017 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
florian3f1d6132015-09-30 20:30:48 +000031#include "pub_core_basics_asm.h"
32
njn8b68b642009-06-24 00:37:09 +000033#if defined(VGP_amd64_linux)
34
njn1a1e95c2009-06-03 06:50:06 +000035#include "pub_core_vkiscnums_asm.h"
sewardj96db5e12005-03-21 17:43:34 +000036#include "libvex_guest_offsets.h"
njnc6168192004-11-29 13:54:10 +000037
njnc6168192004-11-29 13:54:10 +000038
sewardje7aa4ae2005-06-09 12:43:42 +000039/*----------------------------------------------------------------*/
sewardj96db5e12005-03-21 17:43:34 +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 guest_state->guest_RAX. The syscall result
54 is written back to guest_state->guest_RAX on completion.
55
56 Returns 0 if the syscall was successfully called (even if the
57 syscall itself failed), or a -ve error code if one of the
58 sigprocmasks failed (there's no way to determine which one
59 failed).
60
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.
sewardj96db5e12005-03-21 17:43:34 +000064
65 Prototype:
66
sewardj1b9cd1c2005-06-28 19:04:51 +000067 Int ML_(do_syscall_for_client_WRK(
sewardje7aa4ae2005-06-09 12:43:42 +000068 Int syscallno, // rdi
sewardj96db5e12005-03-21 17:43:34 +000069 void* guest_state, // rsi
70 const vki_sigset_t *sysmask, // rdx
71 const vki_sigset_t *postmask, // rcx
njncda2f0f2009-05-18 02:12:08 +000072 Int sigsetSzB) // r8
sewardj96db5e12005-03-21 17:43:34 +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):
philippe2d616332015-05-17 08:24:40 +000081 .cfi_startproc
sewardj96db5e12005-03-21 17:43:34 +000082 /* save callee-saved regs */
83 pushq %rbx
philippe2d616332015-05-17 08:24:40 +000084 .cfi_adjust_cfa_offset 8
85 .cfi_offset %rbx, -16
sewardj96db5e12005-03-21 17:43:34 +000086 pushq %rbp
philippe2d616332015-05-17 08:24:40 +000087 .cfi_adjust_cfa_offset 8
88 .cfi_offset %rbp, -24
sewardj96db5e12005-03-21 17:43:34 +000089 pushq %r12
philippe2d616332015-05-17 08:24:40 +000090 .cfi_adjust_cfa_offset 8
91 .cfi_offset %r12, -32
sewardj96db5e12005-03-21 17:43:34 +000092 pushq %r13
philippe2d616332015-05-17 08:24:40 +000093 .cfi_adjust_cfa_offset 8
94 .cfi_offset %r13, -40
sewardj96db5e12005-03-21 17:43:34 +000095 pushq %r14
philippe2d616332015-05-17 08:24:40 +000096 .cfi_adjust_cfa_offset 8
97 .cfi_offset %r14, -48
sewardj96db5e12005-03-21 17:43:34 +000098 pushq %r15
philippe2d616332015-05-17 08:24:40 +000099 .cfi_adjust_cfa_offset 8
100 .cfi_offset %r15, -56
sewardj96db5e12005-03-21 17:43:34 +0000101
102#define FSZ ((4+1)*4) /* 4 args + ret addr */
103
philippe2d616332015-05-17 08:24:40 +0000104#define PUSH_di_si_dx_cx_8 \
105 pushq %rdi ; \
106 .cfi_adjust_cfa_offset 8 ; \
107 pushq %rsi ; \
108 .cfi_adjust_cfa_offset 8 ; \
109 pushq %rdx ; \
110 .cfi_adjust_cfa_offset 8 ; \
111 pushq %rcx ; \
112 .cfi_adjust_cfa_offset 8 ; \
113 pushq %r8 ; \
114 .cfi_adjust_cfa_offset 8
sewardj96db5e12005-03-21 17:43:34 +0000115
philippe2d616332015-05-17 08:24:40 +0000116#define POP_di_si_dx_cx_8 \
117 popq %r8 ; \
118 .cfi_adjust_cfa_offset -8 ; \
119 popq %rcx ; \
120 .cfi_adjust_cfa_offset -8 ; \
121 popq %rdx ; \
122 .cfi_adjust_cfa_offset -8 ; \
123 popq %rsi ; \
124 .cfi_adjust_cfa_offset -8 ; \
125 popq %rdi ; \
126 .cfi_adjust_cfa_offset -8
sewardj96db5e12005-03-21 17:43:34 +0000127
1281: /* Even though we can't take a signal until the sigprocmask completes,
129 start the range early.
130 If eip is in the range [1,2), the syscall hasn't been started yet */
131
132 /* Set the signal mask which should be current during the syscall. */
133 /* Save and restore all 5 arg regs round the call. This is easier
134 than figuring out the minimal set to save/restore. */
135
136 PUSH_di_si_dx_cx_8
137
sewardjf843ad22005-12-27 01:44:33 +0000138 movq $__NR_rt_sigprocmask, %rax // syscall #
139 movq $VKI_SIG_SETMASK, %rdi // how
140 movq %rdx, %rsi // sysmask
141 movq %rcx, %rdx // postmask
njncda2f0f2009-05-18 02:12:08 +0000142 movq %r8, %r10 // sigsetSzB
sewardjf843ad22005-12-27 01:44:33 +0000143 syscall
sewardj96db5e12005-03-21 17:43:34 +0000144
145 POP_di_si_dx_cx_8
146
sewardjf843ad22005-12-27 01:44:33 +0000147 testq %rax, %rax
148 js 7f /* sigprocmask failed */
sewardj96db5e12005-03-21 17:43:34 +0000149
150 /* OK, that worked. Now do the syscall proper. */
151
152 PUSH_di_si_dx_cx_8
153
sewardjf843ad22005-12-27 01:44:33 +0000154 movq %rsi, %rax /* rax --> VexGuestAMD64State * */
155 pushq %rdi /* syscallno -> stack */
philippe2d616332015-05-17 08:24:40 +0000156 .cfi_adjust_cfa_offset 8
sewardjf843ad22005-12-27 01:44:33 +0000157 movq OFFSET_amd64_RDI(%rax), %rdi
158 movq OFFSET_amd64_RSI(%rax), %rsi
159 movq OFFSET_amd64_RDX(%rax), %rdx
160 movq OFFSET_amd64_R10(%rax), %r10
161 movq OFFSET_amd64_R8(%rax), %r8
162 movq OFFSET_amd64_R9(%rax), %r9
163 popq %rax /* syscallno -> %rax */
philippe2d616332015-05-17 08:24:40 +0000164 .cfi_adjust_cfa_offset -8
sewardj96db5e12005-03-21 17:43:34 +0000165
sewardjf843ad22005-12-27 01:44:33 +0000166 /* If rip==2, then the syscall was either just about
167 to start, or was interrupted and the kernel was
168 restarting it. */
1692: syscall
1703: /* In the range [3, 4), the syscall result is in %rax,
171 but hasn't been committed to RAX. */
sewardj96db5e12005-03-21 17:43:34 +0000172
173 POP_di_si_dx_cx_8
174
175 movq %rax, OFFSET_amd64_RAX(%rsi) /* save back to RAX */
176
sewardjf843ad22005-12-27 01:44:33 +00001774: /* Re-block signals. If eip is in [4,5), then the syscall
178 is complete and we needn't worry about it. */
179
sewardj96db5e12005-03-21 17:43:34 +0000180 PUSH_di_si_dx_cx_8
181
sewardjf843ad22005-12-27 01:44:33 +0000182 movq $__NR_rt_sigprocmask, %rax // syscall #
183 movq $VKI_SIG_SETMASK, %rdi // how
184 movq %rcx, %rsi // postmask
185 xorq %rdx, %rdx // NULL
njncda2f0f2009-05-18 02:12:08 +0000186 movq %r8, %r10 // sigsetSzB
sewardjf843ad22005-12-27 01:44:33 +0000187 syscall
sewardj96db5e12005-03-21 17:43:34 +0000188
189 POP_di_si_dx_cx_8
190
sewardjf843ad22005-12-27 01:44:33 +0000191 testq %rax, %rax
192 js 7f /* sigprocmask failed */
193
sewardj96db5e12005-03-21 17:43:34 +00001945: /* now safe from signals */
sewardjf843ad22005-12-27 01:44:33 +0000195 movq $0, %rax /* SUCCESS */
sewardj96db5e12005-03-21 17:43:34 +0000196 popq %r15
philippe2d616332015-05-17 08:24:40 +0000197 .cfi_adjust_cfa_offset -8
sewardj96db5e12005-03-21 17:43:34 +0000198 popq %r14
philippe2d616332015-05-17 08:24:40 +0000199 .cfi_adjust_cfa_offset -8
sewardj96db5e12005-03-21 17:43:34 +0000200 popq %r13
philippe2d616332015-05-17 08:24:40 +0000201 .cfi_adjust_cfa_offset -8
sewardj96db5e12005-03-21 17:43:34 +0000202 popq %r12
philippe2d616332015-05-17 08:24:40 +0000203 .cfi_adjust_cfa_offset -8
sewardj96db5e12005-03-21 17:43:34 +0000204 popq %rbp
philippe2d616332015-05-17 08:24:40 +0000205 .cfi_adjust_cfa_offset -8
sewardj96db5e12005-03-21 17:43:34 +0000206 popq %rbx
philippe2d616332015-05-17 08:24:40 +0000207 .cfi_adjust_cfa_offset -8
sewardj96db5e12005-03-21 17:43:34 +0000208 ret
philippe2d616332015-05-17 08:24:40 +0000209 .cfi_adjust_cfa_offset 6*8
sewardj96db5e12005-03-21 17:43:34 +0000210
sewardjf843ad22005-12-27 01:44:33 +00002117: /* failure: return 0x8000 | error code */
212 negq %rax
213 andq $0x7FFF, %rax
214 orq $0x8000, %rax
215 popq %r15
philippe2d616332015-05-17 08:24:40 +0000216 .cfi_adjust_cfa_offset -8
sewardjf843ad22005-12-27 01:44:33 +0000217 popq %r14
philippe2d616332015-05-17 08:24:40 +0000218 .cfi_adjust_cfa_offset -8
sewardjf843ad22005-12-27 01:44:33 +0000219 popq %r13
philippe2d616332015-05-17 08:24:40 +0000220 .cfi_adjust_cfa_offset -8
sewardjf843ad22005-12-27 01:44:33 +0000221 popq %r12
philippe2d616332015-05-17 08:24:40 +0000222 .cfi_adjust_cfa_offset -8
sewardjf843ad22005-12-27 01:44:33 +0000223 popq %rbp
philippe2d616332015-05-17 08:24:40 +0000224 .cfi_adjust_cfa_offset -8
sewardjf843ad22005-12-27 01:44:33 +0000225 popq %rbx
philippe2d616332015-05-17 08:24:40 +0000226 .cfi_adjust_cfa_offset -8
sewardjf843ad22005-12-27 01:44:33 +0000227 ret
philippe2d616332015-05-17 08:24:40 +0000228 .cfi_endproc
sewardjf843ad22005-12-27 01:44:33 +0000229#undef FSZ
230
sewardj96db5e12005-03-21 17:43:34 +0000231.section .rodata
sewardj1b9cd1c2005-06-28 19:04:51 +0000232/* export the ranges so that
233 VG_(fixup_guest_state_after_syscall_interrupted) can do the
234 right thing */
sewardj96db5e12005-03-21 17:43:34 +0000235
sewardj1b9cd1c2005-06-28 19:04:51 +0000236.globl ML_(blksys_setup)
237.globl ML_(blksys_restart)
238.globl ML_(blksys_complete)
239.globl ML_(blksys_committed)
240.globl ML_(blksys_finished)
241ML_(blksys_setup): .quad 1b
242ML_(blksys_restart): .quad 2b
243ML_(blksys_complete): .quad 3b
244ML_(blksys_committed): .quad 4b
245ML_(blksys_finished): .quad 5b
sewardj96db5e12005-03-21 17:43:34 +0000246.previous
247
njn8b68b642009-06-24 00:37:09 +0000248#endif // defined(VGP_amd64_linux)
249
florian3f1d6132015-09-30 20:30:48 +0000250/* Let the linker know we don't need an executable stack */
251MARK_STACK_NO_EXEC
252
sewardj0e24d092006-10-17 20:47:13 +0000253/*--------------------------------------------------------------------*/
254/*--- end ---*/
255/*--------------------------------------------------------------------*/