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