Home | History | Annotate | Download | only in coregrind
      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 (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 SysRes 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 */
     99 SysRes 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 */
    107 SysRes 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 
    114 SysRes 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 
    125 SysRes 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 
    136 SysRes 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 */
    149 SysRes 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 */
    158 SysRes 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. */
    168 SysRes 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 
    178 SysRes 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. */
    192 SysRes 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 
    225 SysRes 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. */
    261 SysRes 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 
    269 SysRes 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 */
    299 extern UWord do_syscall_WRK (
    300           UWord syscall_no,
    301           UWord a1, UWord a2, UWord a3,
    302           UWord a4, UWord a5, UWord a6
    303        );
    304 asm(
    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 */
    359 extern UWord do_syscall_WRK (
    360           UWord syscall_no,
    361           UWord a1, UWord a2, UWord a3,
    362           UWord a4, UWord a5, UWord a6
    363        );
    364 asm(
    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 */
    394 extern ULong do_syscall_WRK (
    395           UWord syscall_no,
    396           UWord a1, UWord a2, UWord a3,
    397           UWord a4, UWord a5, UWord a6
    398        );
    399 asm(
    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]. */
    423 extern void do_syscall_WRK ( ULong* argblock );
    424 asm(
    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]. */
    459 extern 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  */
    463 asm(
    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 */
    500 extern UWord do_syscall_WRK (
    501           UWord a1, UWord a2, UWord a3,
    502           UWord a4, UWord a5, UWord a6,
    503           UWord syscall_no
    504        );
    505 asm(
    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 */
    530 extern UWord do_syscall_WRK (
    531           UWord a1, UWord a2, UWord a3,
    532           UWord a4, UWord a5, UWord a6,
    533           UWord syscall_no
    534        );
    535 asm(
    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
    576 do_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
    583 asm(".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
    596 do_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
    601 asm(".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
    609 do_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
    614 asm(
    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
    642 do_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
    650 asm(".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
    666 do_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
    671 asm(".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 
    681 static 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 */
    721 extern 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        );
    726 asm(
    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)
    746 extern UWord do_syscall_WRK ( UWord a1, UWord a2, UWord a3, UWord a4, UWord a5,
    747                               UWord a6, UWord syscall_no, ULong* V1_val );
    748 asm (
    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)
    765 extern UWord do_syscall_WRK (
    766           UWord syscall_no,
    767           UWord a1, UWord a2, UWord a3,
    768           UWord a4, UWord a5, UWord a6
    769        );
    770 asm(
    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 
    793 SysRes 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 
    932 const 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