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-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