1 2 /*--------------------------------------------------------------------*/ 3 /*--- Support for doing system calls. syscall-x86-darwin.S ---*/ 4 /*--------------------------------------------------------------------*/ 5 6 /* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2000-2007 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_x86_darwin) 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 regs->m_eax. The syscall result is written 53 back to regs->m_eax 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, // ebp+8 68 void* guest_state, // ebp+12 69 const vki_sigset_t *sysmask, // ebp+16 70 const vki_sigset_t *postmask, // ebp+20 71 Int sigsetSzB) // ebp+24 72 73 Note that sigsetSzB is totally ignored (and irrelevant). 74 */ 75 76 /* from vki-darwin.h, checked at startup by m_vki.c */ 77 #define VKI_SIG_SETMASK 3 78 79 /* DO_SYSCALL MACH|MDEP|UNIX */ 80 #define MACH 1 81 #define MDEP 2 82 #define UNIX 3 83 84 .macro DO_SYSCALL 85 /* establish stack frame */ 86 push %ebp 87 mov %esp, %ebp 88 subl $$8, %esp /* 16-byte align stack */ 89 90 L_$0_1: /* Even though we can't take a signal until the 91 __pthread_sigmask completes, start the range early. 92 If eip is in the range [1,2), the syscall hasn't been started yet */ 93 94 /* Set the signal mask which should be current during the syscall. */ 95 /* Set up for __pthread_sigmask(SIG_SETMASK, sysmask, postmask) */ 96 pushl 20(%ebp) 97 pushl 16(%ebp) 98 pushl $$VKI_SIG_SETMASK 99 pushl $$0xcafebabe /* totally fake return address */ 100 movl $$__NR___pthread_sigmask, %eax 101 int $$0x80 /* should be sysenter? */ 102 jc L_$0_7 /* __pthread_sigmask failed */ 103 addl $$16,%esp 104 105 /* Copy syscall parameters to the stack - assume no more than 8 106 * plus the return address */ 107 /* do_syscall8 */ 108 /* stack is currently aligned assuming 8 parameters */ 109 movl 12(%ebp), %edx 110 movl OFFSET_x86_ESP(%edx), %edx /* edx = simulated ESP */ 111 movl 28+4(%edx), %eax 112 pushl %eax 113 movl 24+4(%edx), %eax 114 pushl %eax 115 movl 20+4(%edx), %eax 116 pushl %eax 117 movl 16+4(%edx), %eax 118 pushl %eax 119 movl 12+4(%edx), %eax 120 pushl %eax 121 movl 8+4(%edx), %eax 122 pushl %eax 123 movl 4+4(%edx), %eax 124 pushl %eax 125 movl 0+4(%edx), %eax 126 pushl %eax 127 /* return address */ 128 movl 0(%edx), %eax 129 pushl %eax 130 131 /* Put syscall number in eax */ 132 movl 8(%ebp), %eax 133 134 /* If eip==2, then the syscall was either just about to start, 135 or was interrupted and the kernel was restarting it. */ 136 L_$0_2: 137 .if $0 == UNIX 138 int $$0x80 /* UNIX (GrP fixme should be sysenter?) */ 139 .elseif $0 == MACH 140 int $$0x81 141 .elseif $0 == MDEP 142 int $$0x82 143 .else 144 error$0 x 145 .endif 146 147 L_$0_3: /* In the range [3, 4), the syscall result is in %eax and %edx and C, 148 but hasn't been committed to the thread state. */ 149 setc 0(%esp) /* stash returned carry flag */ 150 movl 12(%ebp), %ecx 151 movl %eax, OFFSET_x86_EAX(%ecx) /* save EAX to vex */ 152 movl %edx, OFFSET_x86_EDX(%ecx) /* save EDX to vex */ 153 .if $0 == UNIX 154 /* UNIX: save carry flag to vex */ 155 subl $$12, %esp 156 movl %ecx, 4(%esp) 157 movl $$0, 0(%esp) 158 movb 12(%esp), %al 159 movb %al, 0(%esp) 160 call _LibVEX_GuestX86_put_eflag_c 161 addl $$12, %esp 162 .endif 163 164 L_$0_4: /* Re-block signals. If eip is in [4,5), then the syscall is 165 complete and we needn't worry about it. */ 166 /* Set up for __pthread_sigmask(SIG_SETMASK, postmask, NULL) */ 167 pushl $$0 168 pushl 20(%ebp) 169 pushl $$VKI_SIG_SETMASK 170 pushl $$0xcafef00d /* totally fake return address */ 171 movl $$__NR___pthread_sigmask, %eax 172 int $$0x80 /* should be sysenter? */ 173 jc L_$0_7 /* __pthread_sigmask failed */ 174 addl $$16,%esp 175 176 L_$0_5: /* now safe from signals */ 177 movl $$0, %eax /* SUCCESS */ 178 movl %ebp, %esp 179 popl %ebp 180 ret 181 182 L_$0_7: /* failure: return 0x8000 | error code */ 183 /* Note that we enter here with %esp being 16 too low 184 (4 extra words on the stack). But because we're nuking 185 the stack frame now, that doesn't matter. */ 186 andl $$0x7FFF, %eax 187 orl $$0x8000, %eax 188 movl %ebp, %esp 189 popl %ebp 190 ret 191 192 .endmacro 193 194 195 .globl ML_(do_syscall_for_client_unix_WRK) 196 ML_(do_syscall_for_client_unix_WRK): 197 DO_SYSCALL UNIX 198 199 .globl ML_(do_syscall_for_client_mach_WRK) 200 ML_(do_syscall_for_client_mach_WRK): 201 DO_SYSCALL MACH 202 203 .globl ML_(do_syscall_for_client_mdep_WRK) 204 ML_(do_syscall_for_client_mdep_WRK): 205 DO_SYSCALL MDEP 206 207 .data 208 /* export the ranges so that 209 VG_(fixup_guest_state_after_syscall_interrupted) can do the 210 right thing */ 211 212 /* eg MK_L_SCLASS_N(UNIX,99) produces L_3_99 213 since UNIX is #defined to 3 at the top of this file */ 214 #define FOO(scclass,labelno) L_##scclass##_##labelno 215 #define MK_L_SCCLASS_N(scclass,labelno) FOO(scclass,labelno) 216 217 .globl ML_(blksys_setup_MACH) 218 .globl ML_(blksys_restart_MACH) 219 .globl ML_(blksys_complete_MACH) 220 .globl ML_(blksys_committed_MACH) 221 .globl ML_(blksys_finished_MACH) 222 ML_(blksys_setup_MACH): .long MK_L_SCCLASS_N(MACH,1) 223 ML_(blksys_restart_MACH): .long MK_L_SCCLASS_N(MACH,2) 224 ML_(blksys_complete_MACH): .long MK_L_SCCLASS_N(MACH,3) 225 ML_(blksys_committed_MACH): .long MK_L_SCCLASS_N(MACH,4) 226 ML_(blksys_finished_MACH): .long MK_L_SCCLASS_N(MACH,5) 227 228 .globl ML_(blksys_setup_MDEP) 229 .globl ML_(blksys_restart_MDEP) 230 .globl ML_(blksys_complete_MDEP) 231 .globl ML_(blksys_committed_MDEP) 232 .globl ML_(blksys_finished_MDEP) 233 ML_(blksys_setup_MDEP): .long MK_L_SCCLASS_N(MDEP,1) 234 ML_(blksys_restart_MDEP): .long MK_L_SCCLASS_N(MDEP,2) 235 ML_(blksys_complete_MDEP): .long MK_L_SCCLASS_N(MDEP,3) 236 ML_(blksys_committed_MDEP): .long MK_L_SCCLASS_N(MDEP,4) 237 ML_(blksys_finished_MDEP): .long MK_L_SCCLASS_N(MDEP,5) 238 239 .globl ML_(blksys_setup_UNIX) 240 .globl ML_(blksys_restart_UNIX) 241 .globl ML_(blksys_complete_UNIX) 242 .globl ML_(blksys_committed_UNIX) 243 .globl ML_(blksys_finished_UNIX) 244 ML_(blksys_setup_UNIX): .long MK_L_SCCLASS_N(UNIX,1) 245 ML_(blksys_restart_UNIX): .long MK_L_SCCLASS_N(UNIX,2) 246 ML_(blksys_complete_UNIX): .long MK_L_SCCLASS_N(UNIX,3) 247 ML_(blksys_committed_UNIX): .long MK_L_SCCLASS_N(UNIX,4) 248 ML_(blksys_finished_UNIX): .long MK_L_SCCLASS_N(UNIX,5) 249 250 #endif // defined(VGP_x86_darwin) 251 252 /*--------------------------------------------------------------------*/ 253 /*--- end ---*/ 254 /*--------------------------------------------------------------------*/ 255