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-2015 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 /* Make a SysRes value from a syscall return value. This is 42 platform specific. */ 43 44 #if defined(VGP_mips32_linux) || defined(VGP_mips64_linux) 45 46 SysRes VG_(mk_SysRes_mips32_linux) ( UWord v0, UWord v1, UWord a3 ) { 47 /* MIPS uses a3 != 0 to flag an error */ 48 SysRes res; 49 res._isError = (a3 != (UWord)0); 50 res._val = v0; 51 res._valEx = v1; 52 return res; 53 } 54 55 SysRes VG_(mk_SysRes_mips64_linux) ( ULong v0, ULong v1, ULong a3 ) { 56 /* MIPS uses a3 != 0 to flag an error */ 57 SysRes res; 58 res._isError = (a3 != (ULong)0); 59 res._val = v0; 60 res._valEx = v1; 61 return res; 62 } 63 64 /* Generic constructors. */ 65 SysRes VG_(mk_SysRes_Error) ( UWord err ) { 66 SysRes r; 67 r._isError = True; 68 r._val = err; 69 r._valEx = 0; 70 return r; 71 } 72 73 SysRes VG_(mk_SysRes_Success) ( UWord res ) { 74 SysRes r; 75 r._isError = False; 76 r._val = res; 77 r._valEx = 0; 78 return r; 79 } 80 81 SysRes VG_(mk_SysRes_SuccessEx) ( UWord res, UWord resEx ) { 82 SysRes r; 83 r._isError = False; 84 r._val = res; 85 r._valEx = resEx; 86 return r; 87 } 88 89 90 #elif defined(VGO_linux) \ 91 && !defined(VGP_mips32_linux) && !defined(VGP_mips64_linux) 92 93 /* 94 From: 95 http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/sysdeps/unix/sysv/ 96 linux/i386/sysdep.h? 97 rev=1.28&content-type=text/x-cvsweb-markup&cvsroot=glibc 98 99 Linux uses a negative return value to indicate syscall errors, 100 unlike most Unices, which use the condition codes' carry flag. 101 102 Since version 2.1 the return value of a system call might be 103 negative even if the call succeeded. E.g., the 'lseek' system call 104 might return a large offset. Therefore we must not anymore test 105 for < 0, but test for a real error by making sure the value in %eax 106 is a real error number. Linus said he will make sure the no 107 syscall returns a value in -1 .. -4095 as a valid result so we can 108 safely test with -4095. 109 */ 110 111 SysRes VG_(mk_SysRes_x86_linux) ( Int val ) { 112 SysRes res; 113 res._isError = val >= -4095 && val <= -1; 114 if (res._isError) { 115 res._val = (UInt)(-val); 116 } else { 117 res._val = (UInt)val; 118 } 119 return res; 120 } 121 122 /* Similarly .. */ 123 SysRes VG_(mk_SysRes_amd64_linux) ( Long val ) { 124 SysRes res; 125 res._isError = val >= -4095 && val <= -1; 126 if (res._isError) { 127 res._val = (ULong)(-val); 128 } else { 129 res._val = (ULong)val; 130 } 131 return res; 132 } 133 134 SysRes VG_(mk_SysRes_tilegx_linux) ( Long val ) { 135 SysRes res; 136 res._isError = val >= -4095 && val <= -1; 137 if (res._isError) { 138 res._val = (ULong)(-val); 139 } else { 140 res._val = (ULong)val; 141 } 142 return res; 143 } 144 145 /* PPC uses the CR7.SO bit to flag an error (CR0 in IBM-speak) */ 146 /* Note this must be in the bottom bit of the second arg */ 147 SysRes VG_(mk_SysRes_ppc32_linux) ( UInt val, UInt cr0so ) { 148 SysRes res; 149 res._isError = (cr0so & 1) != 0; 150 res._val = val; 151 return res; 152 } 153 154 /* As per ppc32 version, cr0.so must be in l.s.b. of 2nd arg */ 155 SysRes VG_(mk_SysRes_ppc64_linux) ( ULong val, ULong cr0so ) { 156 SysRes res; 157 res._isError = (cr0so & 1) != 0; 158 res._val = val; 159 return res; 160 } 161 162 SysRes VG_(mk_SysRes_s390x_linux) ( Long val ) { 163 SysRes res; 164 res._isError = val >= -4095 && val <= -1; 165 if (res._isError) { 166 res._val = -val; 167 } else { 168 res._val = val; 169 } 170 return res; 171 } 172 173 SysRes VG_(mk_SysRes_arm_linux) ( Int val ) { 174 SysRes res; 175 res._isError = val >= -4095 && val <= -1; 176 if (res._isError) { 177 res._val = (UInt)(-val); 178 } else { 179 res._val = (UInt)val; 180 } 181 return res; 182 } 183 184 SysRes VG_(mk_SysRes_arm64_linux) ( Long val ) { 185 SysRes res; 186 res._isError = val >= -4095 && val <= -1; 187 if (res._isError) { 188 res._val = (ULong)(-val); 189 } else { 190 res._val = (ULong)val; 191 } 192 return res; 193 } 194 195 /* Generic constructors. */ 196 SysRes VG_(mk_SysRes_Error) ( UWord err ) { 197 SysRes r; 198 r._isError = True; 199 r._val = err; 200 return r; 201 } 202 203 SysRes VG_(mk_SysRes_Success) ( UWord res ) { 204 SysRes r; 205 r._isError = False; 206 r._val = res; 207 return r; 208 } 209 210 211 #elif defined(VGO_darwin) 212 213 /* Darwin: Some syscalls return a double-word result. */ 214 SysRes VG_(mk_SysRes_x86_darwin) ( UChar scclass, Bool isErr, 215 UInt wHI, UInt wLO ) 216 { 217 SysRes res; 218 res._wHI = 0; 219 res._wLO = 0; 220 res._mode = 0; /* invalid */ 221 vg_assert(isErr == False || isErr == True); 222 vg_assert(sizeof(UWord) == sizeof(UInt)); 223 switch (scclass) { 224 case VG_DARWIN_SYSCALL_CLASS_UNIX: 225 res._wLO = wLO; 226 res._wHI = wHI; 227 res._mode = isErr ? SysRes_UNIX_ERR : SysRes_UNIX_OK; 228 break; 229 case VG_DARWIN_SYSCALL_CLASS_MACH: 230 vg_assert(!isErr); 231 vg_assert(wHI == 0); 232 res._wLO = wLO; 233 res._mode = SysRes_MACH; 234 break; 235 case VG_DARWIN_SYSCALL_CLASS_MDEP: 236 vg_assert(!isErr); 237 vg_assert(wHI == 0); 238 res._wLO = wLO; 239 res._mode = SysRes_MDEP; 240 break; 241 default: 242 vg_assert(0); 243 } 244 return res; 245 } 246 247 SysRes VG_(mk_SysRes_amd64_darwin) ( UChar scclass, Bool isErr, 248 ULong wHI, ULong wLO ) 249 { 250 SysRes res; 251 res._wHI = 0; 252 res._wLO = 0; 253 res._mode = 0; /* invalid */ 254 vg_assert(isErr == False || isErr == True); 255 vg_assert(sizeof(UWord) == sizeof(ULong)); 256 switch (scclass) { 257 case VG_DARWIN_SYSCALL_CLASS_UNIX: 258 res._wLO = wLO; 259 res._wHI = wHI; 260 res._mode = isErr ? SysRes_UNIX_ERR : SysRes_UNIX_OK; 261 break; 262 case VG_DARWIN_SYSCALL_CLASS_MACH: 263 vg_assert(!isErr); 264 vg_assert(wHI == 0); 265 res._wLO = wLO; 266 res._mode = SysRes_MACH; 267 break; 268 case VG_DARWIN_SYSCALL_CLASS_MDEP: 269 vg_assert(!isErr); 270 vg_assert(wHI == 0); 271 res._wLO = wLO; 272 res._mode = SysRes_MDEP; 273 break; 274 default: 275 vg_assert(0); 276 } 277 return res; 278 } 279 280 /* Generic constructors. We assume (without checking if this makes 281 any sense, from the caller's point of view) that these are for the 282 UNIX style of syscall. */ 283 SysRes VG_(mk_SysRes_Error) ( UWord err ) { 284 SysRes r; 285 r._wHI = 0; 286 r._wLO = err; 287 r._mode = SysRes_UNIX_ERR; 288 return r; 289 } 290 291 SysRes VG_(mk_SysRes_Success) ( UWord res ) { 292 SysRes r; 293 r._wHI = 0; 294 r._wLO = res; 295 r._mode = SysRes_UNIX_OK; 296 return r; 297 } 298 299 300 #elif defined(VGO_solaris) 301 302 /* Generic constructors. */ 303 SysRes VG_(mk_SysRes_Error) ( UWord err ) { 304 SysRes r; 305 r._val = err; 306 r._val2 = 0; 307 r._isError = True; 308 return r; 309 } 310 311 SysRes VG_(mk_SysRes_Success) ( UWord res ) { 312 SysRes r; 313 r._val = res; 314 r._val2 = 0; 315 r._isError = False; 316 return r; 317 } 318 319 SysRes VG_(mk_SysRes_x86_solaris) ( Bool isErr, UInt val, UInt val2 ) 320 { 321 SysRes res; 322 323 // stay sane 324 vg_assert(isErr == True || isErr == False); 325 326 res._val = val; 327 res._val2 = val2; 328 res._isError = isErr; 329 return res; 330 } 331 332 SysRes VG_(mk_SysRes_amd64_solaris) ( Bool isErr, ULong val, ULong val2 ) 333 { 334 SysRes res; 335 336 // stay sane 337 vg_assert(isErr == True || isErr == False); 338 339 res._val = val; 340 res._val2 = val2; 341 res._isError = isErr; 342 return res; 343 } 344 345 #else 346 # error "Unknown OS" 347 #endif 348 349 350 /* --------------------------------------------------------------------- 351 VG_(do_syscall): A function for doing syscalls. 352 ------------------------------------------------------------------ */ 353 354 #if defined(VGP_x86_linux) 355 /* Incoming args (syscall number + up to 6 args) come on the stack. 356 (ie. the C calling convention). 357 358 The syscall number goes in %eax. The args are passed to the syscall in 359 the regs %ebx, %ecx, %edx, %esi, %edi, %ebp, ie. the kernel's syscall 360 calling convention. 361 362 %eax gets the return value. Not sure which registers the kernel 363 clobbers, so we preserve all the callee-save regs (%esi, %edi, %ebx, 364 %ebp). 365 */ 366 extern UWord do_syscall_WRK ( 367 UWord syscall_no, 368 UWord a1, UWord a2, UWord a3, 369 UWord a4, UWord a5, UWord a6 370 ); 371 asm( 372 ".text\n" 373 ".globl do_syscall_WRK\n" 374 "do_syscall_WRK:\n" 375 " .cfi_startproc\n" 376 " push %esi\n" 377 " .cfi_adjust_cfa_offset 4\n" 378 " .cfi_offset %esi, -8\n" 379 " push %edi\n" 380 " .cfi_adjust_cfa_offset 4\n" 381 " .cfi_offset %edi, -12\n" 382 " push %ebx\n" 383 " .cfi_adjust_cfa_offset 4\n" 384 " .cfi_offset %ebx, -16\n" 385 " push %ebp\n" 386 " .cfi_adjust_cfa_offset 4\n" 387 " .cfi_offset %ebp, -20\n" 388 " movl 16+ 4(%esp),%eax\n" 389 " movl 16+ 8(%esp),%ebx\n" 390 " movl 16+12(%esp),%ecx\n" 391 " movl 16+16(%esp),%edx\n" 392 " movl 16+20(%esp),%esi\n" 393 " movl 16+24(%esp),%edi\n" 394 " movl 16+28(%esp),%ebp\n" 395 " int $0x80\n" 396 " popl %ebp\n" 397 " .cfi_adjust_cfa_offset -4\n" 398 " .cfi_restore %ebp\n" 399 " popl %ebx\n" 400 " .cfi_adjust_cfa_offset -4\n" 401 " .cfi_restore %ebx\n" 402 " popl %edi\n" 403 " .cfi_adjust_cfa_offset -4\n" 404 " .cfi_restore %edi\n" 405 " popl %esi\n" 406 " .cfi_adjust_cfa_offset -4\n" 407 " .cfi_restore %esi\n" 408 " ret\n" 409 " .cfi_endproc\n" 410 ".previous\n" 411 ); 412 413 #elif defined(VGP_amd64_linux) 414 /* Incoming args (syscall number + up to 6 args) come in %rdi, %rsi, 415 %rdx, %rcx, %r8, %r9, and the last one on the stack (ie. the C 416 calling convention). 417 418 The syscall number goes in %rax. The args are passed to the syscall in 419 the regs %rdi, %rsi, %rdx, %r10, %r8, %r9 (yes, really %r10, not %rcx), 420 ie. the kernel's syscall calling convention. 421 422 %rax gets the return value. %rcx and %r11 are clobbered by the syscall; 423 no matter, they are caller-save (the syscall clobbers no callee-save 424 regs, so we don't have to do any register saving/restoring). 425 */ 426 extern UWord do_syscall_WRK ( 427 UWord syscall_no, 428 UWord a1, UWord a2, UWord a3, 429 UWord a4, UWord a5, UWord a6 430 ); 431 asm( 432 ".text\n" 433 ".globl do_syscall_WRK\n" 434 "do_syscall_WRK:\n" 435 /* Convert function calling convention --> syscall calling 436 convention */ 437 " movq %rdi, %rax\n" 438 " movq %rsi, %rdi\n" 439 " movq %rdx, %rsi\n" 440 " movq %rcx, %rdx\n" 441 " movq %r8, %r10\n" 442 " movq %r9, %r8\n" 443 " movq 8(%rsp), %r9\n" /* last arg from stack */ 444 " syscall\n" 445 " ret\n" 446 ".previous\n" 447 ); 448 449 #elif defined(VGP_ppc32_linux) 450 /* Incoming args (syscall number + up to 6 args) come in %r3:%r9. 451 452 The syscall number goes in %r0. The args are passed to the syscall in 453 the regs %r3:%r8, i.e. the kernel's syscall calling convention. 454 455 The %cr0.so bit flags an error. 456 We return the syscall return value in %r3, and the %cr0.so in 457 the lowest bit of %r4. 458 We return a ULong, of which %r3 is the high word, and %r4 the low. 459 No callee-save regs are clobbered, so no saving/restoring is needed. 460 */ 461 extern ULong do_syscall_WRK ( 462 UWord syscall_no, 463 UWord a1, UWord a2, UWord a3, 464 UWord a4, UWord a5, UWord a6 465 ); 466 asm( 467 ".text\n" 468 ".globl do_syscall_WRK\n" 469 "do_syscall_WRK:\n" 470 " mr 0,3\n" 471 " mr 3,4\n" 472 " mr 4,5\n" 473 " mr 5,6\n" 474 " mr 6,7\n" 475 " mr 7,8\n" 476 " mr 8,9\n" 477 " sc\n" /* syscall: sets %cr0.so on error */ 478 " mfcr 4\n" /* %cr -> low word of return var */ 479 " rlwinm 4,4,4,31,31\n" /* rotate flag bit so to lsb, and mask it */ 480 " blr\n" /* and return */ 481 ".previous\n" 482 ); 483 484 #elif defined(VGP_ppc64be_linux) 485 /* Due to the need to return 65 bits of result, this is completely 486 different from the ppc32 case. The single arg register points to a 487 7-word block containing the syscall # and the 6 args. The syscall 488 result proper is put in [0] of the block, and %cr0.so is in the 489 bottom bit of [1]. */ 490 extern void do_syscall_WRK ( ULong* argblock ); 491 asm( 492 ".align 2\n" 493 ".globl do_syscall_WRK\n" 494 ".section \".opd\",\"aw\"\n" 495 ".align 3\n" 496 "do_syscall_WRK:\n" 497 ".quad .do_syscall_WRK,.TOC.@tocbase,0\n" 498 ".previous\n" 499 ".type .do_syscall_WRK,@function\n" 500 ".globl .do_syscall_WRK\n" 501 ".do_syscall_WRK:\n" 502 " std 3,-16(1)\n" /* stash arg */ 503 " ld 8, 48(3)\n" /* sc arg 6 */ 504 " ld 7, 40(3)\n" /* sc arg 5 */ 505 " ld 6, 32(3)\n" /* sc arg 4 */ 506 " ld 5, 24(3)\n" /* sc arg 3 */ 507 " ld 4, 16(3)\n" /* sc arg 2 */ 508 " ld 0, 0(3)\n" /* sc number */ 509 " ld 3, 8(3)\n" /* sc arg 1 */ 510 " sc\n" /* result in r3 and cr0.so */ 511 " ld 5,-16(1)\n" /* reacquire argblock ptr (r5 is caller-save) */ 512 " std 3,0(5)\n" /* argblock[0] = r3 */ 513 " mfcr 3\n" 514 " srwi 3,3,28\n" 515 " andi. 3,3,1\n" 516 " std 3,8(5)\n" /* argblock[1] = cr0.s0 & 1 */ 517 " blr\n" 518 ); 519 520 #elif defined(VGP_ppc64le_linux) 521 /* Due to the need to return 65 bits of result, this is completely 522 different from the ppc32 case. The single arg register points to a 523 7-word block containing the syscall # and the 6 args. The syscall 524 result proper is put in [0] of the block, and %cr0.so is in the 525 bottom bit of [1]. */ 526 extern void do_syscall_WRK ( ULong* argblock ); 527 /* Little Endian supports ELF version 2. In the future, it may support 528 * other versions as well. 529 */ 530 asm( 531 ".align 2\n" 532 ".globl do_syscall_WRK\n" 533 ".type do_syscall_WRK,@function\n" 534 "do_syscall_WRK:\n" 535 "#if _CALL_ELF == 2" "\n" 536 "0: addis 2,12,.TOC.-0b@ha\n" 537 " addi 2,2,.TOC.-0b@l\n" 538 " .localentry do_syscall_WRK, .-do_syscall_WRK\n" 539 "#endif" "\n" 540 " std 3,-16(1)\n" /* stash arg */ 541 " ld 8, 48(3)\n" /* sc arg 6 */ 542 " ld 7, 40(3)\n" /* sc arg 5 */ 543 " ld 6, 32(3)\n" /* sc arg 4 */ 544 " ld 5, 24(3)\n" /* sc arg 3 */ 545 " ld 4, 16(3)\n" /* sc arg 2 */ 546 " ld 0, 0(3)\n" /* sc number */ 547 " ld 3, 8(3)\n" /* sc arg 1 */ 548 " sc\n" /* result in r3 and cr0.so */ 549 " ld 5,-16(1)\n" /* reacquire argblock ptr (r5 is caller-save) */ 550 " std 3,0(5)\n" /* argblock[0] = r3 */ 551 " mfcr 3\n" 552 " srwi 3,3,28\n" 553 " andi. 3,3,1\n" 554 " std 3,8(5)\n" /* argblock[1] = cr0.s0 & 1 */ 555 " blr\n" 556 " .size do_syscall_WRK, .-do_syscall_WRK\n" 557 ); 558 559 #elif defined(VGP_arm_linux) 560 /* I think the conventions are: 561 args in r0 r1 r2 r3 r4 r5 562 sysno in r7 563 return value in r0, w/ same conventions as x86-linux, viz r0 in 564 -4096 .. -1 is an error value. All other values are success 565 values. 566 */ 567 extern UWord do_syscall_WRK ( 568 UWord a1, UWord a2, UWord a3, 569 UWord a4, UWord a5, UWord a6, 570 UWord syscall_no 571 ); 572 asm( 573 ".text\n" 574 ".globl do_syscall_WRK\n" 575 "do_syscall_WRK:\n" 576 " push {r4, r5, r7}\n" 577 " ldr r4, [sp, #12]\n" 578 " ldr r5, [sp, #16]\n" 579 " ldr r7, [sp, #20]\n" 580 " svc 0x0\n" 581 " pop {r4, r5, r7}\n" 582 " bx lr\n" 583 ".previous\n" 584 ); 585 586 #elif defined(VGP_arm64_linux) 587 /* I think the conventions are: 588 args in r0 r1 r2 r3 r4 r5 589 sysno in r8 590 return value in r0, w/ same conventions as x86-linux, viz r0 in 591 -4096 .. -1 is an error value. All other values are success 592 values. 593 594 r0 to r5 remain unchanged, but syscall_no is in r6 and needs 595 to be moved to r8 (??) 596 */ 597 extern UWord do_syscall_WRK ( 598 UWord a1, UWord a2, UWord a3, 599 UWord a4, UWord a5, UWord a6, 600 UWord syscall_no 601 ); 602 asm( 603 ".text\n" 604 ".globl do_syscall_WRK\n" 605 "do_syscall_WRK:\n" 606 " mov x8, x6\n" 607 " mov x6, 0\n" 608 " mov x7, 0\n" 609 " svc 0\n" 610 " ret\n" 611 ".previous\n" 612 ); 613 614 #elif defined(VGP_x86_darwin) 615 616 /* Incoming args (syscall number + up to 8 args) come in on the stack 617 618 The kernel's syscall calling convention is: 619 * the syscall number goes in eax 620 * the args are passed to the syscall on the stack, 621 pushed onto the stack R->L (that is, the usual x86 622 calling conventions, with the leftmost arg at the lowest 623 address) 624 Call instruction: 625 * UNIX: sysenter 626 * UNIX: int $0x80 627 * MACH: int $0x81 628 * MDEP: int $0x82 629 Note that the call type can be determined from the syscall number; 630 there is no need to inspect the actual instruction. Although obviously 631 the instruction must match. 632 Return value: 633 * MACH,MDEP: the return value comes back in eax 634 * UNIX: the return value comes back in edx:eax (hi32:lo32) 635 Error: 636 * MACH,MDEP: no error is returned 637 * UNIX: the carry flag indicates success or failure 638 639 nb here, sizeof(UWord) == sizeof(UInt) 640 */ 641 642 __private_extern__ ULong 643 do_syscall_unix_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */ 644 UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */ 645 UWord a7, UWord a8, /* 28(esp)..32(esp) */ 646 UWord syscall_no, /* 36(esp) */ 647 /*OUT*/UInt* errflag /* 40(esp) */ ); 648 // Unix syscall: 64-bit return in edx:eax, with LSB in eax 649 // error indicated by carry flag: clear=good, set=bad 650 asm(".private_extern _do_syscall_unix_WRK\n" 651 "_do_syscall_unix_WRK:\n" 652 " movl 40(%esp), %ecx \n" /* assume syscall success */ 653 " movl $0, (%ecx) \n" 654 " movl 36(%esp), %eax \n" 655 " int $0x80 \n" 656 " jnc 1f \n" /* jump if success */ 657 " movl 40(%esp), %ecx \n" /* syscall failed - set *errflag */ 658 " movl $1, (%ecx) \n" 659 " 1: ret \n" 660 ); 661 662 __private_extern__ UInt 663 do_syscall_mach_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */ 664 UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */ 665 UWord a7, UWord a8, /* 28(esp)..32(esp) */ 666 UWord syscall_no /* 36(esp) */ ); 667 // Mach trap: 32-bit result in %eax, no error flag 668 asm(".private_extern _do_syscall_mach_WRK\n" 669 "_do_syscall_mach_WRK:\n" 670 " movl 36(%esp), %eax \n" 671 " int $0x81 \n" 672 " ret \n" 673 ); 674 675 __private_extern__ UInt 676 do_syscall_mdep_WRK ( UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */ 677 UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */ 678 UWord a7, UWord a8, /* 28(esp)..32(esp) */ 679 UWord syscall_no /* 36(esp) */ ); 680 // mdep trap: 32-bit result in %eax, no error flag 681 asm( 682 ".private_extern _do_syscall_mdep_WRK\n" 683 "_do_syscall_mdep_WRK:\n" 684 " movl 36(%esp), %eax \n" 685 " int $0x82 \n" 686 " ret \n" 687 ); 688 689 690 #elif defined(VGP_amd64_darwin) 691 692 /* Incoming args (syscall number + up to 8 args) come in registers and stack 693 694 The kernel's syscall calling convention is: 695 * the syscall number goes in rax 696 * the args are passed to the syscall in registers and the stack 697 * the call instruction is 'syscall' 698 Return value: 699 * MACH,MDEP: the return value comes back in rax 700 * UNIX: the return value comes back in rdx:rax (hi64:lo64) 701 Error: 702 * MACH,MDEP: no error is returned 703 * UNIX: the carry flag indicates success or failure 704 705 nb here, sizeof(UWord) == sizeof(ULong) 706 */ 707 708 __private_extern__ UWord 709 do_syscall_unix_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 /*OUT*/ULong* errflag, /* 32(rsp) */ 714 /*OUT*/ULong* res2 ); /* 40(rsp) */ 715 // Unix syscall: 128-bit return in rax:rdx, with LSB in rax 716 // error indicated by carry flag: clear=good, set=bad 717 asm(".private_extern _do_syscall_unix_WRK\n" 718 "_do_syscall_unix_WRK:\n" 719 " movq %rcx, %r10 \n" /* pass rcx in r10 instead */ 720 " movq 32(%rsp), %rax \n" /* assume syscall success */ 721 " movq $0, (%rax) \n" 722 " movq 24(%rsp), %rax \n" /* load syscall_no */ 723 " syscall \n" 724 " jnc 1f \n" /* jump if success */ 725 " movq 32(%rsp), %rcx \n" /* syscall failed - set *errflag */ 726 " movq $1, (%rcx) \n" 727 " 1: movq 40(%rsp), %rcx \n" /* save 2nd result word */ 728 " movq %rdx, (%rcx) \n" 729 " retq \n" /* return 1st result word */ 730 ); 731 732 __private_extern__ UWord 733 do_syscall_mach_WRK ( UWord a1, UWord a2, UWord a3, /* rdi, rsi, rdx */ 734 UWord a4, UWord a5, UWord a6, /* rcx, r8, r9 */ 735 UWord a7, UWord a8, /* 8(rsp), 16(rsp) */ 736 UWord syscall_no ); /* 24(rsp) */ 737 // Mach trap: 64-bit result, no error flag 738 asm(".private_extern _do_syscall_mach_WRK\n" 739 "_do_syscall_mach_WRK:\n" 740 " movq %rcx, %r10 \n" /* pass rcx in r10 instead */ 741 " movq 24(%rsp), %rax \n" /* load syscall_no */ 742 " syscall \n" 743 " retq \n" 744 ); 745 746 #elif defined(VGP_s390x_linux) 747 748 static UWord do_syscall_WRK ( 749 UWord syscall_no, 750 UWord arg1, UWord arg2, UWord arg3, 751 UWord arg4, UWord arg5, UWord arg6 752 ) 753 { 754 register UWord __arg1 asm("2") = arg1; 755 register UWord __arg2 asm("3") = arg2; 756 register UWord __arg3 asm("4") = arg3; 757 register UWord __arg4 asm("5") = arg4; 758 register UWord __arg5 asm("6") = arg5; 759 register UWord __arg6 asm("7") = arg6; 760 register ULong __svcres asm("2"); 761 762 __asm__ __volatile__ ( 763 "lgr %%r1,%1\n\t" 764 "svc 0\n\t" 765 : "=d" (__svcres) 766 : "a" (syscall_no), 767 "0" (__arg1), 768 "d" (__arg2), 769 "d" (__arg3), 770 "d" (__arg4), 771 "d" (__arg5), 772 "d" (__arg6) 773 : "1", "cc", "memory"); 774 775 return (UWord) (__svcres); 776 } 777 778 #elif defined(VGP_mips32_linux) 779 /* Incoming args (syscall number + up to 6 args) come in a0 - a3 and stack. 780 781 The syscall number goes in v0. The args are passed to the syscall in 782 the regs a0 - a3 and stack, i.e. the kernel's syscall calling convention. 783 784 (a3 != 0) flags an error. 785 We return the syscall return value in v0. 786 MIPS version 787 */ 788 extern int do_syscall_WRK ( 789 int a1, int a2, int a3, 790 int a4, int a5, int a6, int syscall_no, UWord *err, 791 UWord *valHi, UWord* valLo 792 ); 793 asm( 794 ".globl do_syscall_WRK\n" 795 ".ent do_syscall_WRK\n" 796 ".text\n" 797 "do_syscall_WRK:\n" 798 " lw $2, 24($29)\n" 799 " syscall\n" 800 " lw $8, 28($29)\n" 801 " sw $7, ($8)\n" 802 " lw $8, 32($29)\n" 803 " sw $3, ($8)\n" // store valHi 804 " lw $8, 36($29)\n" 805 " sw $2, ($8)\n" // store valLo 806 " jr $31\n" 807 " nop\n" 808 ".previous\n" 809 ".end do_syscall_WRK\n" 810 ); 811 812 #elif defined(VGP_mips64_linux) 813 extern UWord do_syscall_WRK ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5, 814 UWord a6, UWord syscall_no, ULong* V1_val ); 815 asm ( 816 ".text\n" 817 ".globl do_syscall_WRK\n" 818 "do_syscall_WRK:\n" 819 " daddiu $29, $29, -8\n" 820 " sd $11, 0($29)\n" 821 " move $2, $10\n" 822 " syscall\n" 823 " ld $11, 0($29)\n" 824 " daddiu $29, $29, 8\n" 825 " sd $3, 0($11)\n" /* store vale of v1 in last param */ 826 " sd $7, 8($11)\n" /* store vale of a3 in last param */ 827 " jr $31\n" 828 ".previous\n" 829 ); 830 831 #elif defined(VGP_tilegx_linux) 832 extern UWord do_syscall_WRK ( 833 UWord syscall_no, 834 UWord a1, UWord a2, UWord a3, 835 UWord a4, UWord a5, UWord a6 836 ); 837 asm( 838 ".text\n" 839 "do_syscall_WRK:\n" 840 "move r10, r0\n" 841 "move r0, r1\n" 842 "move r1, r2\n" 843 "move r2, r3\n" 844 "move r3, r4\n" 845 "move r4, r5\n" 846 "move r5, r6\n" 847 "swint1\n" 848 "jrp lr\n" 849 ".previous\n" 850 ); 851 852 #elif defined(VGP_x86_solaris) 853 854 extern ULong 855 do_syscall_WRK(UWord a1, UWord a2, UWord a3, /* 4(esp)..12(esp) */ 856 UWord a4, UWord a5, UWord a6, /* 16(esp)..24(esp) */ 857 UWord a7, UWord a8, /* 28(esp)..32(esp) */ 858 UWord syscall_no, /* 36(esp) */ 859 /*OUT*/UInt *errflag); /* 40(esp) */ 860 /* Classic unix syscall.. parameters on the stack, an unused (by the kernel) 861 return address at 0(esp), a sysno in eax, a result in edx:eax, the carry 862 flag set on error. */ 863 __asm__ ( 864 ".text\n" 865 ".globl do_syscall_WRK\n" 866 "do_syscall_WRK:\n" 867 " movl 40(%esp), %ecx\n" /* assume syscall success */ 868 " movl $0, (%ecx)\n" 869 " movl 36(%esp), %eax\n" 870 " int $0x91\n" 871 " jnc 1f\n" /* jump if success */ 872 " movl 40(%esp), %ecx\n" /* syscall failed - set *errflag */ 873 " movl $1, (%ecx)\n" 874 "1: ret\n" 875 ".previous\n" 876 ); 877 878 extern ULong 879 do_syscall_fast_WRK(UWord syscall_no); /* 4(esp) */ 880 /* Fasttrap syscall.. no parameters, a sysno in eax, a result in edx:eax, 881 never fails (if the sysno is valid). */ 882 __asm__ ( 883 ".text\n" 884 ".globl do_syscall_fast_WRK\n" 885 "do_syscall_fast_WRK:\n" 886 " movl 4(%esp), %eax\n" 887 " int $0xD2\n" 888 " ret\n" 889 ".previous\n" 890 ); 891 892 #elif defined(VGP_amd64_solaris) 893 894 extern ULong 895 do_syscall_WRK(UWord a1, UWord a2, UWord a3, /* rdi, rsi, rdx */ 896 UWord a4, UWord a5, UWord a6, /* rcx, r8, r9 */ 897 UWord a7, UWord a8, /* 8(rsp), 16(rsp) */ 898 UWord syscall_no, /* 24(rsp) */ 899 /*OUT*/ULong *errflag, /* 32(rsp) */ 900 /*OUT*/ULong *res2); /* 40(rsp) */ 901 /* First 6 parameters in registers rdi, rsi, rdx, r10, r8, r9, next 902 2 parameters on the stack, an unused (by the kernel) return address at 903 0(rsp), a sysno in rax, a result in rdx:rax, the carry flag set on 904 error. */ 905 __asm__ ( 906 ".text\n" 907 ".globl do_syscall_WRK\n" 908 "do_syscall_WRK:\n" 909 " movq %rcx, %r10\n" /* pass rcx in r10 instead */ 910 " movq 32(%rsp), %rcx\n" /* assume syscall success */ 911 " movq $0, (%rcx)\n" 912 " movq 24(%rsp), %rax\n" 913 " syscall\n" 914 " jnc 1f\n" /* jump if success */ 915 " movq 32(%rsp), %rcx\n" /* syscall failed - set *errflag */ 916 " movq $1, (%rcx)\n" 917 "1: movq 40(%rsp), %rcx\n" /* save 2nd result word */ 918 " movq %rdx, (%rcx)\n" 919 " ret\n" 920 ".previous\n" 921 ); 922 923 extern ULong 924 do_syscall_fast_WRK(UWord syscall_no, /* rdi */ 925 /*OUT*/ULong *res2); /* rsi */ 926 /* Fasttrap syscall.. no parameters, a sysno in rax, a result in rdx:rax, 927 never fails (if the sysno is valid). */ 928 __asm__ ( 929 ".text\n" 930 ".globl do_syscall_fast_WRK\n" 931 "do_syscall_fast_WRK:\n" 932 " movq %rdi, %rax\n" 933 " int $0xD2\n" 934 " movq %rdx, (%rsi)\n" /* save 2nd result word */ 935 " ret\n" 936 ".previous\n" 937 ); 938 939 #else 940 # error Unknown platform 941 #endif 942 943 944 /* Finally, the generic code. This sends the call to the right 945 helper. */ 946 947 SysRes VG_(do_syscall) ( UWord sysno, UWord a1, UWord a2, UWord a3, 948 UWord a4, UWord a5, UWord a6, 949 UWord a7, UWord a8 ) 950 { 951 # if defined(VGP_x86_linux) 952 UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6); 953 return VG_(mk_SysRes_x86_linux)( val ); 954 955 # elif defined(VGP_amd64_linux) 956 UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6); 957 return VG_(mk_SysRes_amd64_linux)( val ); 958 959 # elif defined(VGP_ppc32_linux) 960 ULong ret = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6); 961 UInt val = (UInt)(ret>>32); 962 UInt cr0so = (UInt)(ret); 963 return VG_(mk_SysRes_ppc32_linux)( val, cr0so ); 964 965 # elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) 966 ULong argblock[7]; 967 argblock[0] = sysno; 968 argblock[1] = a1; 969 argblock[2] = a2; 970 argblock[3] = a3; 971 argblock[4] = a4; 972 argblock[5] = a5; 973 argblock[6] = a6; 974 do_syscall_WRK( &argblock[0] ); 975 return VG_(mk_SysRes_ppc64_linux)( argblock[0], argblock[1] ); 976 977 # elif defined(VGP_arm_linux) 978 UWord val = do_syscall_WRK(a1,a2,a3,a4,a5,a6,sysno); 979 return VG_(mk_SysRes_arm_linux)( val ); 980 981 # elif defined(VGP_arm64_linux) 982 UWord val = do_syscall_WRK(a1,a2,a3,a4,a5,a6,sysno); 983 return VG_(mk_SysRes_arm64_linux)( val ); 984 985 # elif defined(VGP_x86_darwin) 986 UInt wLO = 0, wHI = 0, err = 0; 987 ULong u64; 988 UChar scclass = VG_DARWIN_SYSNO_CLASS(sysno); 989 switch (scclass) { 990 case VG_DARWIN_SYSCALL_CLASS_UNIX: 991 u64 = do_syscall_unix_WRK(a1,a2,a3,a4,a5,a6,a7,a8, 992 VG_DARWIN_SYSNO_FOR_KERNEL(sysno), &err); 993 wLO = (UInt)u64; 994 wHI = (UInt)(u64 >> 32); 995 break; 996 case VG_DARWIN_SYSCALL_CLASS_MACH: 997 wLO = do_syscall_mach_WRK(a1,a2,a3,a4,a5,a6,a7,a8, 998 VG_DARWIN_SYSNO_FOR_KERNEL(sysno)); 999 err = 0; 1000 break; 1001 case VG_DARWIN_SYSCALL_CLASS_MDEP: 1002 wLO = do_syscall_mdep_WRK(a1,a2,a3,a4,a5,a6,a7,a8, 1003 VG_DARWIN_SYSNO_FOR_KERNEL(sysno)); 1004 err = 0; 1005 break; 1006 default: 1007 vg_assert(0); 1008 break; 1009 } 1010 return VG_(mk_SysRes_x86_darwin)( scclass, err ? True : False, wHI, wLO ); 1011 1012 # elif defined(VGP_amd64_darwin) 1013 ULong wLO = 0, wHI = 0, err = 0; 1014 UChar scclass = VG_DARWIN_SYSNO_CLASS(sysno); 1015 switch (scclass) { 1016 case VG_DARWIN_SYSCALL_CLASS_UNIX: 1017 wLO = do_syscall_unix_WRK(a1,a2,a3,a4,a5,a6,a7,a8, 1018 VG_DARWIN_SYSNO_FOR_KERNEL(sysno), &err, &wHI); 1019 break; 1020 case VG_DARWIN_SYSCALL_CLASS_MACH: 1021 case VG_DARWIN_SYSCALL_CLASS_MDEP: 1022 wLO = do_syscall_mach_WRK(a1,a2,a3,a4,a5,a6,a7,a8, 1023 VG_DARWIN_SYSNO_FOR_KERNEL(sysno)); 1024 err = 0; 1025 break; 1026 default: 1027 vg_assert(0); 1028 break; 1029 } 1030 return VG_(mk_SysRes_amd64_darwin)( scclass, err ? True : False, wHI, wLO ); 1031 1032 #elif defined(VGP_s390x_linux) 1033 UWord val; 1034 1035 if (sysno == __NR_mmap) { 1036 ULong argbuf[6]; 1037 1038 argbuf[0] = a1; 1039 argbuf[1] = a2; 1040 argbuf[2] = a3; 1041 argbuf[3] = a4; 1042 argbuf[4] = a5; 1043 argbuf[5] = a6; 1044 val = do_syscall_WRK(sysno,(UWord)&argbuf[0],0,0,0,0,0); 1045 } else { 1046 val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6); 1047 } 1048 1049 return VG_(mk_SysRes_s390x_linux)( val ); 1050 1051 #elif defined(VGP_mips32_linux) 1052 UWord err = 0; 1053 UWord valHi = 0; 1054 UWord valLo = 0; 1055 (void) do_syscall_WRK(a1,a2,a3,a4,a5,a6, sysno,&err,&valHi,&valLo); 1056 return VG_(mk_SysRes_mips32_linux)( valLo, valHi, (ULong)err ); 1057 1058 #elif defined(VGP_mips64_linux) 1059 ULong v1_a3[2]; 1060 v1_a3[0] = 0xFF00; 1061 v1_a3[1] = 0xFF00; 1062 ULong V0 = do_syscall_WRK(a1,a2,a3,a4,a5,a6,sysno,v1_a3); 1063 ULong V1 = (ULong)v1_a3[0]; 1064 ULong A3 = (ULong)v1_a3[1]; 1065 return VG_(mk_SysRes_mips64_linux)( V0, V1, A3 ); 1066 1067 # elif defined(VGP_tilegx_linux) 1068 UWord val = do_syscall_WRK(sysno,a1,a2,a3,a4,a5,a6); 1069 1070 return VG_(mk_SysRes_tilegx_linux)( val ); 1071 1072 # elif defined(VGP_x86_solaris) 1073 UInt val, val2, err = False; 1074 Bool restart; 1075 ULong u64; 1076 UChar ssclass = VG_SOLARIS_SYSNO_CLASS(sysno); 1077 1078 switch (ssclass) { 1079 case VG_SOLARIS_SYSCALL_CLASS_CLASSIC: 1080 /* The Solaris kernel does not restart syscalls automatically so it 1081 is done here. */ 1082 do { 1083 u64 = do_syscall_WRK(a1,a2,a3,a4,a5,a6,a7,a8, 1084 VG_SOLARIS_SYSNO_INDEX(sysno), &err); 1085 val = (UInt)u64; 1086 restart = err && (val == VKI_EINTR || val == VKI_ERESTART); 1087 } while (restart); 1088 break; 1089 case VG_SOLARIS_SYSCALL_CLASS_FASTTRAP: 1090 u64 = do_syscall_fast_WRK(VG_SOLARIS_SYSNO_INDEX(sysno)); 1091 break; 1092 default: 1093 vg_assert(0); 1094 break; 1095 } 1096 1097 val = (UInt)u64; 1098 val2 = (UInt)(u64 >> 32); 1099 return VG_(mk_SysRes_x86_solaris)(err ? True : False, val, 1100 err ? 0 : val2); 1101 1102 # elif defined(VGP_amd64_solaris) 1103 ULong val, val2, err = False; 1104 Bool restart; 1105 UChar ssclass = VG_SOLARIS_SYSNO_CLASS(sysno); 1106 1107 switch (ssclass) { 1108 case VG_SOLARIS_SYSCALL_CLASS_CLASSIC: 1109 /* The Solaris kernel does not restart syscalls automatically so it 1110 is done here. */ 1111 do { 1112 val = do_syscall_WRK(a1,a2,a3,a4,a5,a6,a7,a8, 1113 VG_SOLARIS_SYSNO_INDEX(sysno), &err, &val2); 1114 restart = err && (val == VKI_EINTR || val == VKI_ERESTART); 1115 } while (restart); 1116 break; 1117 case VG_SOLARIS_SYSCALL_CLASS_FASTTRAP: 1118 val = do_syscall_fast_WRK(VG_SOLARIS_SYSNO_INDEX(sysno), &val2); 1119 break; 1120 default: 1121 vg_assert(0); 1122 break; 1123 } 1124 1125 return VG_(mk_SysRes_amd64_solaris)(err ? True : False, val, 1126 err ? 0 : val2); 1127 1128 #else 1129 # error Unknown platform 1130 #endif 1131 } 1132 1133 /* --------------------------------------------------------------------- 1134 Names of errors. 1135 ------------------------------------------------------------------ */ 1136 1137 /* Return a string which gives the name of an error value. Note, 1138 unlike the standard C syserror fn, the returned string is not 1139 malloc-allocated or writable -- treat it as a constant. 1140 TODO: implement this properly. */ 1141 1142 const HChar* VG_(strerror) ( UWord errnum ) 1143 { 1144 switch (errnum) { 1145 case VKI_EPERM: return "Operation not permitted"; 1146 case VKI_ENOENT: return "No such file or directory"; 1147 case VKI_ESRCH: return "No such process"; 1148 case VKI_EINTR: return "Interrupted system call"; 1149 case VKI_EIO: return "Input/output error"; 1150 case VKI_ENXIO: return "No such device or address"; 1151 case VKI_E2BIG: return "Argument list too long"; 1152 case VKI_ENOEXEC: return "Exec format error"; 1153 case VKI_EBADF: return "Bad file descriptor"; 1154 case VKI_ECHILD: return "No child processes"; 1155 case VKI_EAGAIN: return "Resource temporarily unavailable"; 1156 case VKI_ENOMEM: return "Cannot allocate memory"; 1157 case VKI_EACCES: return "Permission denied"; 1158 case VKI_EFAULT: return "Bad address"; 1159 case VKI_ENOTBLK: return "Block device required"; 1160 case VKI_EBUSY: return "Device or resource busy"; 1161 case VKI_EEXIST: return "File exists"; 1162 case VKI_EXDEV: return "Invalid cross-device link"; 1163 case VKI_ENODEV: return "No such device"; 1164 case VKI_ENOTDIR: return "Not a directory"; 1165 case VKI_EISDIR: return "Is a directory"; 1166 case VKI_EINVAL: return "Invalid argument"; 1167 case VKI_ENFILE: return "Too many open files in system"; 1168 case VKI_EMFILE: return "Too many open files"; 1169 case VKI_ENOTTY: return "Inappropriate ioctl for device"; 1170 case VKI_ETXTBSY: return "Text file busy"; 1171 case VKI_EFBIG: return "File too large"; 1172 case VKI_ENOSPC: return "No space left on device"; 1173 case VKI_ESPIPE: return "Illegal seek"; 1174 case VKI_EROFS: return "Read-only file system"; 1175 case VKI_EMLINK: return "Too many links"; 1176 case VKI_EPIPE: return "Broken pipe"; 1177 case VKI_EDOM: return "Numerical argument out of domain"; 1178 case VKI_ERANGE: return "Numerical result out of range"; 1179 1180 case VKI_ENOSYS: return "Function not implemented"; 1181 case VKI_EOVERFLOW: return "Value too large for defined data type"; 1182 # if defined(VKI_ERESTARTSYS) 1183 case VKI_ERESTARTSYS: return "ERESTARTSYS"; 1184 # endif 1185 default: return "VG_(strerror): unknown error"; 1186 } 1187 } 1188 1189 1190 /*--------------------------------------------------------------------*/ 1191 /*--- end ---*/ 1192 /*--------------------------------------------------------------------*/ 1193