1 2 /*--------------------------------------------------------------------*/ 3 /*--- Doing syscalls. m_syscall.c ---*/ 4 /*--------------------------------------------------------------------*/ 5 6 /* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2000-2010 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 #include "pub_core_basics.h" 32 #include "pub_core_libcassert.h" 33 #include "pub_core_vki.h" 34 #include "pub_core_vkiscnums.h" 35 #include "pub_core_syscall.h" 36 37 /* --------------------------------------------------------------------- 38 Building syscall return values. 39 ------------------------------------------------------------------ */ 40 41 #if defined(VGO_linux) 42 43 /* Make a SysRes value from a syscall return value. This is 44 Linux-specific. 45 46 From: 47 http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/sysdeps/unix/sysv/ 48 linux/i386/sysdep.h? 49 rev=1.28&content-type=text/x-cvsweb-markup&cvsroot=glibc 50 51 Linux uses a negative return value to indicate syscall errors, 52 unlike most Unices, which use the condition codes' carry flag. 53 54 Since version 2.1 the return value of a system call might be 55 negative even if the call succeeded. E.g., the 'lseek' system call 56 might return a large offset. Therefore we must not anymore test 57 for < 0, but test for a real error by making sure the value in %eax 58 is a real error number. Linus said he will make sure the no 59 syscall returns a value in -1 .. -4095 as a valid result so we can 60 safely test with -4095. 61 */ 62 63 SysRes VG_(mk_SysRes_x86_linux) ( Int val ) { 64 SysRes res; 65 res._isError = val >= -4095 && val <= -1; 66 if (res._isError) { 67 res._val = (UInt)(-val); 68 } else { 69 res._val = (UInt)val; 70 } 71 return res; 72 } 73 74 /* Similarly .. */ 75 SysRes VG_(mk_SysRes_amd64_linux) ( Long val ) { 76 SysRes res; 77 res._isError = val >= -4095 && val <= -1; 78 if (res._isError) { 79 res._val = (ULong)(-val); 80 } else { 81 res._val = (ULong)val; 82 } 83 return res; 84 } 85 86 /* PPC uses the CR7.SO bit to flag an error (CR0 in IBM-speak) */ 87 /* Note this must be in the bottom bit of the second arg */ 88 SysRes VG_(mk_SysRes_ppc32_linux) ( UInt val, UInt cr0so ) { 89 SysRes res; 90 res._isError = (cr0so & 1) != 0; 91 res._val = val; 92 return res; 93 } 94 95 /* As per ppc32 version, cr0.so must be in l.s.b. of 2nd arg */ 96 SysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong cr0so ) { 97 SysRes res; 98 res._isError = (cr0so & 1) != 0; 99 res._val = val; 100 return res; 101 } 102 103 SysRes VG_(mk_SysRes_arm_linux) ( Int val ) { 104 SysRes res; 105 res._isError = val >= -4095 && val <= -1; 106 if (res._isError) { 107 res._val = (UInt)(-val); 108 } else { 109 res._val = (UInt)val; 110 } 111 return res; 112 } 113 114 /* Generic constructors. */ 115 SysRes VG_(mk_SysRes_Error) ( UWord err ) { 116 SysRes r; 117 r._isError = True; 118 r._val = err; 119 return r; 120 } 121 122 SysRes VG_(mk_SysRes_Success) ( UWord res ) { 123 SysRes r; 124 r._isError = False; 125 r._val = res; 126 return r; 127 } 128 129 130 #elif defined(VGO_aix5) 131 132 /* AIX scheme: we have to record both 'res' (r3) and 'err' (r4). If 133 'err' is nonzero then the call has failed, but it could still be 134 that AIX userspace will ignore 'err' and instead consult 'res' to 135 determine if the call failed. So we have to record both. */ 136 SysRes VG_(mk_SysRes_ppc32_aix5) ( UInt res, UInt err ) { 137 SysRes r; 138 r.res = res; 139 r.err = err; 140 r.isError = r.err != 0; 141 return r; 142 } 143 144 SysRes VG_(mk_SysRes_ppc64_aix5) ( ULong res, ULong err ) { 145 SysRes r; 146 r.res = res; 147 r.err = err; 148 r.isError = r.err != 0; 149 return r; 150 } 151 152 /* Generic constructors. */ 153 SysRes VG_(mk_SysRes_Error) ( UWord err ) { 154 SysRes r; 155 r._res = 0; 156 r._err = err; 157 r._isError = True; 158 return r; 159 } 160 161 SysRes VG_(mk_SysRes_Success) ( UWord res ) { 162 SysRes r; 163 r._res = res; 164 r._err = 0; 165 r._isError = False; 166 return r; 167 } 168 169 170 #elif defined(VGO_darwin) 171 172 /* Darwin: Some syscalls return a double-word result. */ 173 SysRes VG_(mk_SysRes_x86_darwin) ( UChar scclass, Bool isErr, 174 UInt wHI, UInt wLO ) 175 { 176 SysRes res; 177 res._wHI = 0; 178 res._wLO = 0; 179 res._mode = 0; /* invalid */ 180 vg_assert(isErr == False || isErr == True); 181 vg_assert(sizeof(UWord) == sizeof(UInt)); 182 switch (scclass) { 183 case VG_DARWIN_SYSCALL_CLASS_UNIX: 184 res._wLO = wLO; 185 res._wHI = wHI; 186 res._mode = isErr ? SysRes_UNIX_ERR : SysRes_UNIX_OK; 187 break; 188 case VG_DARWIN_SYSCALL_CLASS_MACH: 189 vg_assert(!isErr); 190 vg_assert(wHI == 0); 191 res._wLO = wLO; 192 res._mode = SysRes_MACH; 193 break; 194 case VG_DARWIN_SYSCALL_CLASS_MDEP: 195 vg_assert(!isErr); 196 vg_assert(wHI == 0); 197 res._wLO = wLO; 198 res._mode = SysRes_MDEP; 199 break; 200 default: 201 vg_assert(0); 202 } 203 return res; 204 } 205 206 SysRes VG_(mk_SysRes_amd64_darwin) ( UChar scclass, Bool isErr, 207 ULong wHI, ULong wLO ) 208 { 209 SysRes res; 210 res._wHI = 0; 211 res._wLO = 0; 212 res._mode = 0; /* invalid */ 213 vg_assert(isErr == False || isErr == True); 214 vg_assert(sizeof(UWord) == sizeof(ULong)); 215 switch (scclass) { 216 case VG_DARWIN_SYSCALL_CLASS_UNIX: 217 res._wLO = wLO; 218 res._wHI = wHI; 219 res._mode = isErr ? SysRes_UNIX_ERR : SysRes_UNIX_OK; 220 break; 221 case VG_DARWIN_SYSCALL_CLASS_MACH: 222 vg_assert(!isErr); 223 vg_assert(wHI == 0); 224 res._wLO = wLO; 225 res._mode = SysRes_MACH; 226 break; 227 case VG_DARWIN_SYSCALL_CLASS_MDEP: 228 vg_assert(!isErr); 229 vg_assert(wHI == 0); 230 res._wLO = wLO; 231 res._mode = SysRes_MDEP; 232 break; 233 default: 234 vg_assert(0); 235 } 236 return res; 237 } 238 239 /* Generic constructors. We assume (without checking if this makes 240 any sense, from the caller's point of view) that these are for the 241 UNIX style of syscall. */ 242 SysRes VG_(mk_SysRes_Error) ( UWord err ) { 243 SysRes r; 244 r._wHI = 0; 245 r._wLO = err; 246 r._mode = SysRes_UNIX_ERR; 247 return r; 248 } 249 250 SysRes VG_(mk_SysRes_Success) ( UWord res ) { 251 SysRes r; 252 r._wHI = 0; 253 r._wLO = res; 254 r._mode = SysRes_UNIX_OK; 255 return r; 256 } 257 258 259 #else 260 # error "Unknown OS" 261 #endif 262 263 264 /* --------------------------------------------------------------------- 265 VG_(do_syscall): A function for doing syscalls. 266 ------------------------------------------------------------------ */ 267 268 #if defined(VGP_x86_linux) 269 /* Incoming args (syscall number + up to 6 args) come on the stack. 270 (ie. the C calling convention). 271 272 The syscall number goes in %eax. The args are passed to the syscall in 273 the regs %ebx, %ecx, %edx, %esi, %edi, %ebp, ie. the kernel's syscall 274 calling convention. 275 276 %eax gets the return value. Not sure which registers the kernel 277 clobbers, so we preserve all the callee-save regs (%esi, %edi, %ebx, 278 %ebp). 279 */ 280 extern UWord do_syscall_WRK ( 281 UWord syscall_no, 282 UWord a1, UWord a2, UWord a3, 283 UWord a4, UWord a5, UWord a6 284 ); 285 asm( 286 ".text\n" 287 "do_syscall_WRK:\n" 288 " push %esi\n" 289 " push %edi\n" 290 " push %ebx\n" 291 " push %ebp\n" 292 " movl 16+ 4(%esp),%eax\n" 293 " movl 16+ 8(%esp),%ebx\n" 294 " movl 16+12(%esp),%ecx\n" 295 " movl 16+16(%esp),%edx\n" 296 " movl 16+20(%esp),%esi\n" 297 " movl 16+24(%esp),%edi\n" 298 " movl 16+28(%esp),%ebp\n" 299 " int $0x80\n" 300 " popl %ebp\n" 301 " popl %ebx\n" 302 " popl %edi\n" 303 " popl %esi\n" 304 " ret\n" 305 ".previous\n" 306 ); 307 308 #elif defined(VGP_amd64_linux) 309 /* Incoming args (syscall number + up to 6 args) come in %rdi, %rsi, 310 %rdx, %rcx, %r8, %r9, and the last one on the stack (ie. the C 311 calling convention). 312 313 The syscall number goes in %rax. The args are passed to the syscall in 314 the regs %rdi, %rsi, %rdx, %r10, %r8, %r9 (yes, really %r10, not %rcx), 315 ie. the kernel's syscall calling convention. 316 317 %rax gets the return value. %rcx and %r11 are clobbered by the syscall; 318 no matter, they are caller-save (the syscall clobbers no callee-save 319 regs, so we don't have to do any register saving/restoring). 320 */ 321 extern UWord do_syscall_WRK ( 322 UWord syscall_no, 323 UWord a1, UWord a2, UWord a3, 324 UWord a4, UWord a5, UWord a6 325 ); 326 asm( 327 ".text\n" 328 "do_syscall_WRK:\n" 329 /* Convert function calling convention --> syscall calling 330 convention */ 331 " movq %rdi, %rax\n" 332 " movq %rsi, %rdi\n" 333 " movq %rdx, %rsi\n" 334 " movq %rcx, %rdx\n" 335 " movq %r8, %r10\n" 336 " movq %r9, %r8\n" 337 " movq 8(%rsp), %r9\n" /* last arg from stack */ 338 " syscall\n" 339 " ret\n" 340 ".previous\n" 341 ); 342 343 #elif defined(VGP_ppc32_linux) 344 /* Incoming args (syscall number + up to 6 args) come in %r3:%r9. 345 346 The syscall number goes in %r0. The args are passed to the syscall in 347 the regs %r3:%r8, i.e. the kernel's syscall calling convention. 348 349 The %cr0.so bit flags an error. 350 We return the syscall return value in %r3, and the %cr0.so in 351 the lowest bit of %r4. 352 We return a ULong, of which %r3 is the high word, and %r4 the low. 353 No callee-save regs are clobbered, so no saving/restoring is needed. 354 */ 355 extern ULong do_syscall_WRK ( 356 UWord syscall_no, 357 UWord a1, UWord a2, UWord a3, 358 UWord a4, UWord a5, UWord a6 359 ); 360 asm( 361 ".text\n" 362 "do_syscall_WRK:\n" 363 " mr 0,3\n" 364 " mr 3,4\n" 365 " mr 4,5\n" 366 " mr 5,6\n" 367 " mr 6,7\n" 368 " mr 7,8\n" 369 " mr 8,9\n" 370 " sc\n" /* syscall: sets %cr0.so on error */ 371 " mfcr 4\n" /* %cr -> low word of return var */ 372 " rlwinm 4,4,4,31,31\n" /* rotate flag bit so to lsb, and mask it */ 373 " blr\n" /* and return */ 374 ".previous\n" 375 ); 376 377 #elif defined(VGP_ppc64_linux) 378 /* Due to the need to return 65 bits of result, this is completely 379 different from the ppc32 case. The single arg register points to a 380 7-word block containing the syscall # and the 6 args. The syscall 381 result proper is put in [0] of the block, and %cr0.so is in the 382 bottom bit of [1]. */ 383 extern void do_syscall_WRK ( ULong* argblock ); 384 asm( 385 ".align 2\n" 386 ".globl do_syscall_WRK\n" 387 ".section \".opd\",\"aw\"\n" 388 ".align 3\n" 389 "do_syscall_WRK:\n" 390 ".quad .do_syscall_WRK,.TOC.@tocbase,0\n" 391 ".previous\n" 392 ".type .do_syscall_WRK,@function\n" 393 ".globl .do_syscall_WRK\n" 394 ".do_syscall_WRK:\n" 395 " std 3,-16(1)\n" /* stash arg */ 396 " ld 8, 48(3)\n" /* sc arg 6 */ 397 " ld 7, 40(3)\n" /* sc arg 5 */ 398 " ld 6, 32(3)\n" /* sc arg 4 */ 399 " ld 5, 24(3)\n" /* sc arg 3 */ 400 " ld 4, 16(3)\n" /* sc arg 2 */ 401 " ld 0, 0(3)\n" /* sc number */ 402 " ld 3, 8(3)\n" /* sc arg 1 */ 403 " sc\n" /* result in r3 and cr0.so */ 404 " ld 5,-16(1)\n" /* reacquire argblock ptr (r5 is caller-save) */ 405 " std 3,0(5)\n" /* argblock[0] = r3 */ 406 " mfcr 3\n" 407 " srwi 3,3,28\n" 408 " andi. 3,3,1\n" 409 " std 3,8(5)\n" /* argblock[1] = cr0.s0 & 1 */ 410 " blr\n" 411 ); 412 413 #elif defined(VGP_arm_linux) 414 /* I think the conventions are: 415 args in r0 r1 r2 r3 r4 r5 416 sysno in r7 417 return value in r0, w/ same conventions as x86-linux, viz r0 in 418 -4096 .. -1 is an error value. All other values are success 419 values. 420 */ 421 extern UWord do_syscall_WRK ( 422 UWord a1, UWord a2, UWord a3, 423 UWord a4, UWord a5, UWord a6, 424 UWord syscall_no 425 ); 426 asm( 427 ".text\n" 428 "do_syscall_WRK:\n" 429 " push {r4, r5, r7}\n" 430 " ldr r4, [sp, #12]\n" 431 " ldr r5, [sp, #16]\n" 432 " ldr r7, [sp, #20]\n" 433 " svc 0x0\n" 434 " pop {r4, r5, r7}\n" 435 " bx lr\n" 436 ".previous\n" 437 ); 438 439 #elif defined(VGP_ppc32_aix5) 440 static void do_syscall_WRK ( UWord* res_r3, UWord* res_r4, 441 UWord sysno, 442 UWord a1, UWord a2, UWord a3, 443 UWord a4, UWord a5, UWord a6, 444 UWord a7, UWord a8 ) 445 { 446 /* Syscalls on AIX are very similar to function calls: 447 - up to 8 args in r3-r10 448 - syscall number in r2 449 - kernel resumes at 'lr', so must set it appropriately beforehand 450 - r3 holds the result and r4 any applicable error code 451 See http://www.cs.utexas.edu/users/cart/publications/tr00-04.ps 452 and also 'man truss'. 453 */ 454 /* For some reason gcc-3.3.2 doesn't preserve r31 across the asm 455 even though we state it to be trashed. So use r27 instead. */ 456 UWord args[9]; 457 args[0] = sysno; 458 args[1] = a1; args[2] = a2; 459 args[3] = a3; args[4] = a4; 460 args[5] = a5; args[6] = a6; 461 args[7] = a7; args[8] = a8; 462 463 __asm__ __volatile__( 464 465 // establish base ptr 466 "mr 28,%0\n\t" 467 468 // save r2, lr 469 "mr 27,2\n\t" // save r2 in r27 470 "mflr 30\n\t" // save lr in r30 471 472 // set syscall number and args 473 "lwz 2, 0(28)\n\t" 474 "lwz 3, 4(28)\n\t" 475 "lwz 4, 8(28)\n\t" 476 "lwz 5, 12(28)\n\t" 477 "lwz 6, 16(28)\n\t" 478 "lwz 7, 20(28)\n\t" 479 "lwz 8, 24(28)\n\t" 480 "lwz 9, 28(28)\n\t" 481 "lwz 10, 32(28)\n\t" 482 483 // set bit 3 of CR1 otherwise AIX 5.1 returns to the 484 // wrong address after the sc instruction 485 "crorc 6,6,6\n\t" 486 487 // set up LR to point just after the sc insn 488 ".long 0x48000005\n\t" // "bl here+4" -- lr := & next insn 489 "mflr 29\n\t" 490 "addi 29,29,16\n\t" 491 "mtlr 29\n\t" 492 493 // do it! 494 "sc\n\t" 495 496 // result is now in r3; save it in args[0] 497 "stw 3,0(28)\n\t" 498 // error code in r4; save it in args[1] 499 "stw 4,4(28)\n\t" 500 501 // restore 502 "mr 2,27\n\t" 503 "mtlr 30\n\t" 504 505 : /*out*/ 506 : /*in*/ "b" (&args[0]) 507 : /*trash*/ 508 /*temps*/ "r31","r30","r29","r28","r27", 509 /*args*/ "r3","r4","r5","r6","r7","r8","r9","r10", 510 /*paranoia*/ "memory","cc","r0","r1","r11","r12","r13", 511 "xer","ctr","cr0","cr1","cr2","cr3", 512 "cr4","cr5","cr6","cr7" 513 ); 514 515 *res_r3 = args[0]; 516 *res_r4 = args[1]; 517 } 518 519 #elif defined(VGP_ppc64_aix5) 520 static void do_syscall_WRK ( UWord* res_r3, UWord* res_r4, 521 UWord sysno, 522 UWord a1, UWord a2, UWord a3, 523 UWord a4, UWord a5, UWord a6, 524 UWord a7, UWord a8 ) 525 { 526 /* Same scheme as ppc32-aix5. */ 527 UWord args[9]; 528 args[0] = sysno; 529 args[1] = a1; args[2] = a2; 530 args[3] = a3; args[4] = a4; 531 args[5] = a5; args[6] = a6; 532 args[7] = a7; args[8] = a8; 533 534 __asm__ __volatile__( 535 536 // establish base ptr 537 "mr 28,%0\n\t" 538 539 // save r2, lr 540 "mr 27,2\n\t" // save r2 in r27 541 "mflr 30\n\t" // save lr in r30 542 543 // set syscall number and args 544 "ld 2, 0(28)\n\t" 545 "ld 3, 8(28)\n\t" 546 "ld 4, 16(28)\n\t" 547 "ld 5, 24(28)\n\t" 548 "ld 6, 32(28)\n\t" 549 "ld 7, 40(28)\n\t" 550 "ld 8, 48(28)\n\t" 551 "ld 9, 56(28)\n\t" 552 "ld 10, 64(28)\n\t" 553 554 // set bit 3 of CR1 otherwise AIX 5.1 returns to the 555 // wrong address after the sc instruction 556 "crorc 6,6,6\n\t" 557 558 // set up LR to point just after the sc insn 559 ".long 0x48000005\n\t" // "bl here+4" -- lr := & next insn 560 "mflr 29\n\t" 561 "addi 29,29,16\n\t" 562 "mtlr 29\n\t" 563 564 // do it! 565 "sc\n\t" 566 567 // result is now in r3; save it in args[0] 568 "std 3,0(28)\n\t" 569 // error code in r4; save it in args[1] 570 "std 4,8(28)\n\t" 571 572 // restore 573 "mr 2,27\n\t" 574 "mtlr 30\n\t" 575 576 : /*out*/ 577 : /*in*/ "b" (&args[0]) 578 : /*trash*/ 579 /*temps*/ "r31","r30","r29","r28","r27", 580 /*args*/ "r3","r4","r5","r6","r7","r8","r9","r10", 581 /*paranoia*/ "memory","cc","r0","r1","r11","r12","r13", 582 "xer","ctr","cr0","cr1","cr2","cr3", 583 "cr4","cr5","cr6","cr7" 584 ); 585 586 *res_r3 = args[0]; 587 *res_r4 = args[1]; 588 } 589 590 #elif defined(VGP_x86_darwin) 591 592 /* Incoming args (syscall number + up to 8 args) come in on the stack 593 594 The kernel's syscall calling convention is: 595 * the syscall number goes in eax 596 * the args are passed to the syscall on the stack, 597 pushed onto the stack R->L (that is, the usual x86 598 calling conventions, with the leftmost arg at the lowest 599 address) 600 Call instruction: 601 * UNIX: sysenter 602 * UNIX: int $0x80 603 * MACH: int $0x81 604 * MDEP: int $0x82 605 Note that the call type can be determined from the syscall number; 606 there is no need to inspect the actual instruction. Although obviously 607 the instruction must match. 608 Return value: 609 * MACH,MDEP: the return value comes back in eax 610 * UNIX: the return value comes back in edx:eax (hi32:lo32) 611 Error: 612 * MACH,MDEP: no error is returned 613 * UNIX: the carry flag indicates success or failure 614 615 nb here, sizeof(UWord) == sizeof(UInt) 616 */ 617 618 __private_extern__ ULong 619 do_syscall_unix_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */ 620 UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */ 621 UWord a7, UWord a8, /* 28(esp)..32(esp) */ 622 UWord syscall_no, /* 36(esp) */ 623 /*OUT*/UInt* errflag /* 40(esp) */ ); 624 // Unix syscall: 64-bit return in edx:eax, with LSB in eax 625 // error indicated by carry flag: clear=good, set=bad 626 asm(".private_extern _do_syscall_unix_WRK\n" 627 "_do_syscall_unix_WRK:\n" 628 " movl 40(%esp), %ecx \n" /* assume syscall success */ 629 " movl $0, (%ecx) \n" 630 " movl 36(%esp), %eax \n" 631 " int $0x80 \n" 632 " jnc 1f \n" /* jump if success */ 633 " movl 40(%esp), %ecx \n" /* syscall failed - set *errflag */ 634 " movl $1, (%ecx) \n" 635 " 1: ret \n" 636 ); 637 638 __private_extern__ UInt 639 do_syscall_mach_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */ 640 UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */ 641 UWord a7, UWord a8, /* 28(esp)..32(esp) */ 642 UWord syscall_no /* 36(esp) */ ); 643 // Mach trap: 32-bit result in %eax, no error flag 644 asm(".private_extern _do_syscall_mach_WRK\n" 645 "_do_syscall_mach_WRK:\n" 646 " movl 36(%esp), %eax \n" 647 " int $0x81 \n" 648 " ret \n" 649 ); 650 651 __private_extern__ UInt 652 do_syscall_mdep_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */ 653 UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */ 654 UWord a7, UWord a8, /* 28(esp)..32(esp) */ 655 UWord syscall_no /* 36(esp) */ ); 656 // mdep trap: 32-bit result in %eax, no error flag 657 asm( 658 ".private_extern _do_syscall_mdep_WRK\n" 659 "_do_syscall_mdep_WRK:\n" 660 " movl 36(%esp), %eax \n" 661 " int $0x82 \n" 662 " ret \n" 663 ); 664 665 666 #elif defined(VGP_amd64_darwin) 667 668 /* Incoming args (syscall number + up to 8 args) come in registers and stack 669 670 The kernel's syscall calling convention is: 671 * the syscall number goes in rax 672 * the args are passed to the syscall in registers and the stack 673 * the call instruction is 'syscall' 674 Return value: 675 * MACH,MDEP: the return value comes back in rax 676 * UNIX: the return value comes back in rdx:rax (hi64:lo64) 677 Error: 678 * MACH,MDEP: no error is returned 679 * UNIX: the carry flag indicates success or failure 680 681 nb here, sizeof(UWord) == sizeof(ULong) 682 */ 683 684 __private_extern__ UWord 685 do_syscall_unix_WRK ( UWord a1, UWord a2, UWord a3, /* rdi, rsi, rdx */ 686 UWord a4, UWord a5, UWord a6, /* rcx, r8, r9 */ 687 UWord a7, UWord a8, /* 8(rsp), 16(rsp) */ 688 UWord syscall_no, /* 24(rsp) */ 689 /*OUT*/ULong* errflag, /* 32(rsp) */ 690 /*OUT*/ULong* res2 ); /* 40(rsp) */ 691 // Unix syscall: 128-bit return in rax:rdx, with LSB in rax 692 // error indicated by carry flag: clear=good, set=bad 693 asm(".private_extern _do_syscall_unix_WRK\n" 694 "_do_syscall_unix_WRK:\n" 695 " movq %rcx, %r10 \n" /* pass rcx in r10 instead */ 696 " movq 32(%rsp), %rax \n" /* assume syscall success */ 697 " movq $0, (%rax) \n" 698 " movq 24(%rsp), %rax \n" /* load syscall_no */ 699 " syscall \n" 700 " jnc 1f \n" /* jump if success */ 701 " movq 32(%rsp), %rcx \n" /* syscall failed - set *errflag */ 702 " movq $1, (%rcx) \n" 703 " 1: movq 40(%rsp), %rcx \n" /* save 2nd result word */ 704 " movq %rdx, (%rcx) \n" 705 " retq \n" /* return 1st result word */ 706 ); 707 708 __private_extern__ UWord 709 do_syscall_mach_WRK ( UWord a1, UWord a2, UWord a3, /* rdi, rsi, rdx */ 710 UWord a4, UWord a5, UWord a6, /* rcx, r8, r9 */ 711 UWord a7, UWord a8, /* 8(rsp), 16(rsp) */ 712 UWord syscall_no ); /* 24(rsp) */ 713 // Mach trap: 64-bit result, no error flag 714 asm(".private_extern _do_syscall_mach_WRK\n" 715 "_do_syscall_mach_WRK:\n" 716 " movq %rcx, %r10 \n" /* pass rcx in r10 instead */ 717 " movq 24(%rsp), %rax \n" /* load syscall_no */ 718 " syscall \n" 719 " retq \n" 720 ); 721 722 #else 723 # error Unknown platform 724 #endif 725 726 727 /* Finally, the generic code. This sends the call to the right 728 helper. */ 729 730 SysRes VG_(do_syscall) ( UWord sysno, UWord a1, UWord a2, UWord a3, 731 UWord a4, UWord a5, UWord a6, 732 UWord a7, UWord a8 ) 733 { 734 # if defined(VGP_x86_linux) 735 UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6); 736 return VG_(mk_SysRes_x86_linux)( val ); 737 738 # elif defined(VGP_amd64_linux) 739 UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6); 740 return VG_(mk_SysRes_amd64_linux)( val ); 741 742 # elif defined(VGP_ppc32_linux) 743 ULong ret = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6); 744 UInt val = (UInt)(ret>>32); 745 UInt cr0so = (UInt)(ret); 746 return VG_(mk_SysRes_ppc32_linux)( val, cr0so ); 747 748 # elif defined(VGP_ppc64_linux) 749 ULong argblock[7]; 750 argblock[0] = sysno; 751 argblock[1] = a1; 752 argblock[2] = a2; 753 argblock[3] = a3; 754 argblock[4] = a4; 755 argblock[5] = a5; 756 argblock[6] = a6; 757 do_syscall_WRK( &argblock[0] ); 758 return VG_(mk_SysRes_ppc64_linux)( argblock[0], argblock[1] ); 759 760 # elif defined(VGP_arm_linux) 761 UWord val = do_syscall_WRK(a1,a2,a3,a4,a5,a6,sysno); 762 return VG_(mk_SysRes_arm_linux)( val ); 763 764 # elif defined(VGP_ppc32_aix5) 765 UWord res; 766 UWord err; 767 do_syscall_WRK( &res, &err, 768 sysno, a1, a2, a3, a4, a5, a6, a7, a8); 769 /* Try to set the error number to zero if the syscall hasn't 770 really failed. */ 771 if (sysno == __NR_AIX5_kread 772 || sysno == __NR_AIX5_kwrite) { 773 if (res != (UWord)-1L) 774 err = 0; 775 } 776 else if (sysno == __NR_AIX5_sigprocmask 777 || sysno == __NR_AIX5__sigpending) { 778 if (res == 0) 779 err = 0; 780 } 781 return VG_(mk_SysRes_ppc32_aix5)( res, err ); 782 783 # elif defined(VGP_ppc64_aix5) 784 UWord res; 785 UWord err; 786 do_syscall_WRK( &res, &err, 787 sysno, a1, a2, a3, a4, a5, a6, a7, a8); 788 /* Try to set the error number to zero if the syscall hasn't 789 really failed. */ 790 if (sysno == __NR_AIX5_kread 791 || sysno == __NR_AIX5_kwrite) { 792 if (res != (UWord)-1L) 793 err = 0; 794 } 795 else if (sysno == __NR_AIX5_sigprocmask 796 || sysno == __NR_AIX5__sigpending) { 797 if (res == 0) 798 err = 0; 799 } 800 return VG_(mk_SysRes_ppc64_aix5)( res, err ); 801 802 # elif defined(VGP_x86_darwin) 803 UInt wLO = 0, wHI = 0, err = 0; 804 ULong u64; 805 UChar scclass = VG_DARWIN_SYSNO_CLASS(sysno); 806 switch (scclass) { 807 case VG_DARWIN_SYSCALL_CLASS_UNIX: 808 u64 = do_syscall_unix_WRK(a1,a2,a3,a4,a5,a6,a7,a8, 809 VG_DARWIN_SYSNO_FOR_KERNEL(sysno), &err); 810 wLO = (UInt)u64; 811 wHI = (UInt)(u64 >> 32); 812 break; 813 case VG_DARWIN_SYSCALL_CLASS_MACH: 814 wLO = do_syscall_mach_WRK(a1,a2,a3,a4,a5,a6,a7,a8, 815 VG_DARWIN_SYSNO_FOR_KERNEL(sysno)); 816 err = 0; 817 break; 818 case VG_DARWIN_SYSCALL_CLASS_MDEP: 819 wLO = do_syscall_mdep_WRK(a1,a2,a3,a4,a5,a6,a7,a8, 820 VG_DARWIN_SYSNO_FOR_KERNEL(sysno)); 821 err = 0; 822 break; 823 default: 824 vg_assert(0); 825 break; 826 } 827 return VG_(mk_SysRes_x86_darwin)( scclass, err ? True : False, wHI, wLO ); 828 829 # elif defined(VGP_amd64_darwin) 830 ULong wLO = 0, wHI = 0, err = 0; 831 UChar scclass = VG_DARWIN_SYSNO_CLASS(sysno); 832 switch (scclass) { 833 case VG_DARWIN_SYSCALL_CLASS_UNIX: 834 wLO = do_syscall_unix_WRK(a1,a2,a3,a4,a5,a6,a7,a8, 835 VG_DARWIN_SYSNO_FOR_KERNEL(sysno), &err, &wHI); 836 break; 837 case VG_DARWIN_SYSCALL_CLASS_MACH: 838 case VG_DARWIN_SYSCALL_CLASS_MDEP: 839 wLO = do_syscall_mach_WRK(a1,a2,a3,a4,a5,a6,a7,a8, 840 VG_DARWIN_SYSNO_FOR_KERNEL(sysno)); 841 err = 0; 842 break; 843 default: 844 vg_assert(0); 845 break; 846 } 847 return VG_(mk_SysRes_amd64_darwin)( scclass, err ? True : False, wHI, wLO ); 848 849 #else 850 # error Unknown platform 851 #endif 852 } 853 854 /* --------------------------------------------------------------------- 855 Names of errors. 856 ------------------------------------------------------------------ */ 857 858 /* Return a string which gives the name of an error value. Note, 859 unlike the standard C syserror fn, the returned string is not 860 malloc-allocated or writable -- treat it as a constant. 861 TODO: implement this properly. */ 862 863 const HChar* VG_(strerror) ( UWord errnum ) 864 { 865 switch (errnum) { 866 case VKI_EPERM: return "Operation not permitted"; 867 case VKI_ENOENT: return "No such file or directory"; 868 case VKI_ESRCH: return "No such process"; 869 case VKI_EINTR: return "Interrupted system call"; 870 case VKI_EBADF: return "Bad file number"; 871 case VKI_EAGAIN: return "Try again"; 872 case VKI_ENOMEM: return "Out of memory"; 873 case VKI_EACCES: return "Permission denied"; 874 case VKI_EFAULT: return "Bad address"; 875 case VKI_EEXIST: return "File exists"; 876 case VKI_EINVAL: return "Invalid argument"; 877 case VKI_EMFILE: return "Too many open files"; 878 case VKI_ENOSYS: return "Function not implemented"; 879 case VKI_EOVERFLOW: return "Value too large for defined data type"; 880 # if defined(VKI_ERESTARTSYS) 881 case VKI_ERESTARTSYS: return "ERESTARTSYS"; 882 # endif 883 default: return "VG_(strerror): unknown error"; 884 } 885 } 886 887 888 /*--------------------------------------------------------------------*/ 889 /*--- end ---*/ 890 /*--------------------------------------------------------------------*/ 891