1 2 /*--------------------------------------------------------------------*/ 3 /*--- Support for doing system calls. syscall-amd64-linux.S ---*/ 4 /*--------------------------------------------------------------------*/ 5 6 /* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2000-2012 Julian Seward 11 jseward (at) 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 31 #if defined(VGP_amd64_linux) 32 33 #include "pub_core_basics_asm.h" 34 #include "pub_core_vkiscnums_asm.h" 35 #include "libvex_guest_offsets.h" 36 37 38 /*----------------------------------------------------------------*/ 39 /* 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 60 VG_(fixup_guest_state_after_syscall_interrupted) does the 61 thread state fixup in the case where we were interrupted by a 62 signal. 63 64 Prototype: 65 66 Int ML_(do_syscall_for_client_WRK( 67 Int syscallno, // rdi 68 void* guest_state, // rsi 69 const vki_sigset_t *sysmask, // rdx 70 const vki_sigset_t *postmask, // rcx 71 Int sigsetSzB) // r8 72 73 */ 74 75 /* from vki_arch.h */ 76 #define VKI_SIG_SETMASK 2 77 78 .globl ML_(do_syscall_for_client_WRK) 79 ML_(do_syscall_for_client_WRK): 80 /* 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 104 1: /* 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 114 movq $__NR_rt_sigprocmask, %rax // syscall # 115 movq $VKI_SIG_SETMASK, %rdi // how 116 movq %rdx, %rsi // sysmask 117 movq %rcx, %rdx // postmask 118 movq %r8, %r10 // sigsetSzB 119 syscall 120 121 POP_di_si_dx_cx_8 122 123 testq %rax, %rax 124 js 7f /* sigprocmask failed */ 125 126 /* OK, that worked. Now do the syscall proper. */ 127 128 PUSH_di_si_dx_cx_8 129 130 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 */ 139 140 /* If rip==2, then the syscall was either just about 141 to start, or was interrupted and the kernel was 142 restarting it. */ 143 2: syscall 144 3: /* In the range [3, 4), the syscall result is in %rax, 145 but hasn't been committed to RAX. */ 146 147 POP_di_si_dx_cx_8 148 149 movq %rax, OFFSET_amd64_RAX(%rsi) /* save back to RAX */ 150 151 4: /* Re-block signals. If eip is in [4,5), then the syscall 152 is complete and we needn't worry about it. */ 153 154 PUSH_di_si_dx_cx_8 155 156 movq $__NR_rt_sigprocmask, %rax // syscall # 157 movq $VKI_SIG_SETMASK, %rdi // how 158 movq %rcx, %rsi // postmask 159 xorq %rdx, %rdx // NULL 160 movq %r8, %r10 // sigsetSzB 161 syscall 162 163 POP_di_si_dx_cx_8 164 165 testq %rax, %rax 166 js 7f /* sigprocmask failed */ 167 168 5: /* now safe from signals */ 169 movq $0, %rax /* SUCCESS */ 170 popq %r15 171 popq %r14 172 popq %r13 173 popq %r12 174 popq %rbp 175 popq %rbx 176 ret 177 178 7: /* 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 191 .section .rodata 192 /* export the ranges so that 193 VG_(fixup_guest_state_after_syscall_interrupted) can do the 194 right thing */ 195 196 .globl ML_(blksys_setup) 197 .globl ML_(blksys_restart) 198 .globl ML_(blksys_complete) 199 .globl ML_(blksys_committed) 200 .globl ML_(blksys_finished) 201 ML_(blksys_setup): .quad 1b 202 ML_(blksys_restart): .quad 2b 203 ML_(blksys_complete): .quad 3b 204 ML_(blksys_committed): .quad 4b 205 ML_(blksys_finished): .quad 5b 206 .previous 207 208 /* Let the linker know we don't need an executable stack */ 209 .section .note.GNU-stack,"",@progbits 210 211 #endif // defined(VGP_amd64_linux) 212 213 /*--------------------------------------------------------------------*/ 214 /*--- end ---*/ 215 /*--------------------------------------------------------------------*/ 216