Home | History | Annotate | Download | only in m_syswrap
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- Platform-specific syscalls stuff.      syswrap-amd64-linux.c ---*/
      4 /*--------------------------------------------------------------------*/
      5 
      6 /*
      7    This file is part of Valgrind, a dynamic binary instrumentation
      8    framework.
      9 
     10    Copyright (C) 2000-2010 Nicholas Nethercote
     11       njn (at) valgrind.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 #if defined(VGP_amd64_linux)
     32 
     33 #include "pub_core_basics.h"
     34 #include "pub_core_vki.h"
     35 #include "pub_core_vkiscnums.h"
     36 #include "pub_core_threadstate.h"
     37 #include "pub_core_aspacemgr.h"
     38 #include "pub_core_debuglog.h"
     39 #include "pub_core_options.h"
     40 #include "pub_core_libcbase.h"
     41 #include "pub_core_libcassert.h"
     42 #include "pub_core_libcprint.h"
     43 #include "pub_core_libcproc.h"
     44 #include "pub_core_libcsignal.h"
     45 #include "pub_core_scheduler.h"
     46 #include "pub_core_sigframe.h"
     47 #include "pub_core_signals.h"
     48 #include "pub_core_syscall.h"
     49 #include "pub_core_syswrap.h"
     50 #include "pub_core_tooliface.h"
     51 #include "pub_core_stacks.h"        // VG_(register_stack)
     52 
     53 #include "priv_types_n_macros.h"
     54 #include "priv_syswrap-generic.h"   /* for decls of generic wrappers */
     55 #include "priv_syswrap-linux.h"     /* for decls of linux-ish wrappers */
     56 #include "priv_syswrap-linux-variants.h" /* decls of linux variant wrappers */
     57 #include "priv_syswrap-main.h"
     58 
     59 
     60 /* ---------------------------------------------------------------------
     61    clone() handling
     62    ------------------------------------------------------------------ */
     63 
     64 /* Call f(arg1), but first switch stacks, using 'stack' as the new
     65    stack, and use 'retaddr' as f's return-to address.  Also, clear all
     66    the integer registers before entering f.  */
     67 __attribute__((noreturn))
     68 void ML_(call_on_new_stack_0_1) ( Addr stack,
     69 			          Addr retaddr,
     70 			          void (*f)(Word),
     71                                   Word arg1 );
     72 // %rdi == stack
     73 // %rsi == retaddr
     74 // %rdx == f
     75 // %rcx == arg1
     76 asm(
     77 ".text\n"
     78 ".globl vgModuleLocal_call_on_new_stack_0_1\n"
     79 "vgModuleLocal_call_on_new_stack_0_1:\n"
     80 "   movq   %rdi, %rsp\n"   // set stack
     81 "   pushq  %rsi\n"         // retaddr to stack
     82 "   pushq  %rdx\n"         // f to stack
     83 "   pushq  %rcx\n"         // arg1 to stack
     84 "   movq $0, %rax\n"       // zero all GP regs
     85 "   movq $0, %rbx\n"
     86 "   movq $0, %rcx\n"
     87 "   movq $0, %rdx\n"
     88 "   movq $0, %rsi\n"
     89 "   movq $0, %rdi\n"
     90 "   movq $0, %rbp\n"
     91 "   movq $0, %r8\n"
     92 "   movq $0, %r9\n"
     93 "   movq $0, %r10\n"
     94 "   movq $0, %r11\n"
     95 "   movq $0, %r12\n"
     96 "   movq $0, %r13\n"
     97 "   movq $0, %r14\n"
     98 "   movq $0, %r15\n"
     99 "   popq   %rdi\n"         // arg1 to correct arg reg
    100 "   ret\n"                 // jump to f
    101 "   ud2\n"                 // should never get here
    102 ".previous\n"
    103 );
    104 
    105 /*
    106         Perform a clone system call.  clone is strange because it has
    107         fork()-like return-twice semantics, so it needs special
    108         handling here.
    109 
    110 	Upon entry, we have:
    111 
    112 	    int (*fn)(void*)	in %rdi
    113 	    void*  child_stack	in %rsi
    114 	    int    flags	in %rdx
    115 	    void*  arg		in %rcx
    116 	    pid_t* child_tid	in %r8
    117 	    pid_t* parent_tid	in %r9
    118 	    void*  tls_ptr      at 8(%rsp)
    119 
    120 	System call requires:
    121 
    122 	    int    $__NR_clone  in %rax
    123 	    int    flags	in %rdi
    124 	    void*  child_stack	in %rsi
    125 	    pid_t* parent_tid	in %rdx
    126 	    pid_t* child_tid	in %r10
    127 	    void*  tls_ptr      in %r8
    128 
    129 	Returns a Long encoded in the linux-amd64 way, not a SysRes.
    130  */
    131 #define __NR_CLONE        VG_STRINGIFY(__NR_clone)
    132 #define __NR_EXIT         VG_STRINGIFY(__NR_exit)
    133 
    134 extern
    135 Long do_syscall_clone_amd64_linux ( Word (*fn)(void *),
    136                                     void* stack,
    137                                     Long  flags,
    138                                     void* arg,
    139                                     Long* child_tid,
    140                                     Long* parent_tid,
    141                                     vki_modify_ldt_t * );
    142 asm(
    143 ".text\n"
    144 "do_syscall_clone_amd64_linux:\n"
    145         // set up child stack, temporarily preserving fn and arg
    146 "       subq    $16, %rsi\n"            // make space on stack
    147 "       movq    %rcx, 8(%rsi)\n"        // save arg
    148 "       movq    %rdi, 0(%rsi)\n"        // save fn
    149 
    150         // setup syscall
    151 "       movq    $"__NR_CLONE", %rax\n"  // syscall number
    152 "       movq    %rdx,     %rdi\n"       // syscall arg1: flags
    153         // %rsi already setup           // syscall arg2: child_stack
    154 "       movq    %r9,      %rdx\n"       // syscall arg3: parent_tid
    155 "       movq    %r8,      %r10\n"       // syscall arg4: child_tid
    156 "       movq    8(%rsp),  %r8\n"        // syscall arg5: tls_ptr
    157 
    158 "       syscall\n"                      // clone()
    159 
    160 "       testq   %rax, %rax\n"           // child if retval == 0
    161 "       jnz     1f\n"
    162 
    163         // CHILD - call thread function
    164 "       pop     %rax\n"                 // pop fn
    165 "       pop     %rdi\n"                 // pop fn arg1: arg
    166 "       call    *%rax\n"                // call fn
    167 
    168         // exit with result
    169 "       movq    %rax, %rdi\n"           // arg1: return value from fn
    170 "       movq    $"__NR_EXIT", %rax\n"
    171 
    172 "       syscall\n"
    173 
    174         // Exit returned?!
    175 "       ud2\n"
    176 
    177 "1:\n"  // PARENT or ERROR
    178 "       ret\n"
    179 ".previous\n"
    180 );
    181 
    182 #undef __NR_CLONE
    183 #undef __NR_EXIT
    184 
    185 
    186 // forward declaration
    187 static void setup_child ( ThreadArchState*, ThreadArchState* );
    188 
    189 /*
    190    When a client clones, we need to keep track of the new thread.  This means:
    191    1. allocate a ThreadId+ThreadState+stack for the the thread
    192 
    193    2. initialize the thread's new VCPU state
    194 
    195    3. create the thread using the same args as the client requested,
    196    but using the scheduler entrypoint for EIP, and a separate stack
    197    for ESP.
    198  */
    199 static SysRes do_clone ( ThreadId ptid,
    200                          ULong flags, Addr rsp,
    201                          Long* parent_tidptr,
    202                          Long* child_tidptr,
    203                          Addr tlsaddr )
    204 {
    205    static const Bool debug = False;
    206 
    207    ThreadId     ctid = VG_(alloc_ThreadState)();
    208    ThreadState* ptst = VG_(get_ThreadState)(ptid);
    209    ThreadState* ctst = VG_(get_ThreadState)(ctid);
    210    UWord*       stack;
    211    NSegment const* seg;
    212    SysRes       res;
    213    Long         rax;
    214    vki_sigset_t blockall, savedmask;
    215 
    216    VG_(sigfillset)(&blockall);
    217 
    218    vg_assert(VG_(is_running_thread)(ptid));
    219    vg_assert(VG_(is_valid_tid)(ctid));
    220 
    221    stack = (UWord*)ML_(allocstack)(ctid);
    222    if (stack == NULL) {
    223       res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
    224       goto out;
    225    }
    226 
    227    /* Copy register state
    228 
    229       Both parent and child return to the same place, and the code
    230       following the clone syscall works out which is which, so we
    231       don't need to worry about it.
    232 
    233       The parent gets the child's new tid returned from clone, but the
    234       child gets 0.
    235 
    236       If the clone call specifies a NULL rsp for the new thread, then
    237       it actually gets a copy of the parent's rsp.
    238    */
    239    setup_child( &ctst->arch, &ptst->arch );
    240 
    241    /* Make sys_clone appear to have returned Success(0) in the
    242       child. */
    243    ctst->arch.vex.guest_RAX = 0;
    244 
    245    if (rsp != 0)
    246       ctst->arch.vex.guest_RSP = rsp;
    247 
    248    ctst->os_state.parent = ptid;
    249 
    250    /* inherit signal mask */
    251    ctst->sig_mask = ptst->sig_mask;
    252    ctst->tmp_sig_mask = ptst->sig_mask;
    253 
    254    /* Start the child with its threadgroup being the same as the
    255       parent's.  This is so that any exit_group calls that happen
    256       after the child is created but before it sets its
    257       os_state.threadgroup field for real (in thread_wrapper in
    258       syswrap-linux.c), really kill the new thread.  a.k.a this avoids
    259       a race condition in which the thread is unkillable (via
    260       exit_group) because its threadgroup is not set.  The race window
    261       is probably only a few hundred or a few thousand cycles long.
    262       See #226116. */
    263    ctst->os_state.threadgroup = ptst->os_state.threadgroup;
    264 
    265    /* We don't really know where the client stack is, because its
    266       allocated by the client.  The best we can do is look at the
    267       memory mappings and try to derive some useful information.  We
    268       assume that esp starts near its highest possible value, and can
    269       only go down to the start of the mmaped segment. */
    270    seg = VG_(am_find_nsegment)((Addr)rsp);
    271    if (seg && seg->kind != SkResvn) {
    272       ctst->client_stack_highest_word = (Addr)VG_PGROUNDUP(rsp);
    273       ctst->client_stack_szB = ctst->client_stack_highest_word - seg->start;
    274 
    275       VG_(register_stack)(seg->start, ctst->client_stack_highest_word);
    276 
    277       if (debug)
    278 	 VG_(printf)("tid %d: guessed client stack range %#lx-%#lx\n",
    279 		     ctid, seg->start, VG_PGROUNDUP(rsp));
    280    } else {
    281       VG_(message)(Vg_UserMsg,
    282                    "!? New thread %d starts with RSP(%#lx) unmapped\n",
    283 		   ctid, rsp);
    284       ctst->client_stack_szB  = 0;
    285    }
    286 
    287    /* Assume the clone will succeed, and tell any tool that wants to
    288       know that this thread has come into existence.  If the clone
    289       fails, we'll send out a ll_exit notification for it at the out:
    290       label below, to clean up. */
    291    VG_TRACK ( pre_thread_ll_create, ptid, ctid );
    292 
    293    if (flags & VKI_CLONE_SETTLS) {
    294       if (debug)
    295 	 VG_(printf)("clone child has SETTLS: tls at %#lx\n", tlsaddr);
    296       ctst->arch.vex.guest_FS_ZERO = tlsaddr;
    297    }
    298 
    299    flags &= ~VKI_CLONE_SETTLS;
    300 
    301    /* start the thread with everything blocked */
    302    VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
    303 
    304    /* Create the new thread */
    305    rax = do_syscall_clone_amd64_linux(
    306             ML_(start_thread_NORETURN), stack, flags, &VG_(threads)[ctid],
    307             child_tidptr, parent_tidptr, NULL
    308          );
    309    res = VG_(mk_SysRes_amd64_linux)( rax );
    310 
    311    VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
    312 
    313   out:
    314    if (sr_isError(res)) {
    315       /* clone failed */
    316       VG_(cleanup_thread)(&ctst->arch);
    317       ctst->status = VgTs_Empty;
    318       /* oops.  Better tell the tool the thread exited in a hurry :-) */
    319       VG_TRACK( pre_thread_ll_exit, ctid );
    320    }
    321 
    322    return res;
    323 }
    324 
    325 
    326 /* ---------------------------------------------------------------------
    327    More thread stuff
    328    ------------------------------------------------------------------ */
    329 
    330 void VG_(cleanup_thread) ( ThreadArchState *arch )
    331 {
    332 }
    333 
    334 void setup_child ( /*OUT*/ ThreadArchState *child,
    335                    /*IN*/  ThreadArchState *parent )
    336 {
    337    /* We inherit our parent's guest state. */
    338    child->vex = parent->vex;
    339    child->vex_shadow1 = parent->vex_shadow1;
    340    child->vex_shadow2 = parent->vex_shadow2;
    341 }
    342 
    343 
    344 /* ---------------------------------------------------------------------
    345    PRE/POST wrappers for AMD64/Linux-specific syscalls
    346    ------------------------------------------------------------------ */
    347 
    348 #define PRE(name)       DEFN_PRE_TEMPLATE(amd64_linux, name)
    349 #define POST(name)      DEFN_POST_TEMPLATE(amd64_linux, name)
    350 
    351 /* Add prototypes for the wrappers declared here, so that gcc doesn't
    352    harass us for not having prototypes.  Really this is a kludge --
    353    the right thing to do is to make these wrappers 'static' since they
    354    aren't visible outside this file, but that requires even more macro
    355    magic. */
    356 DECL_TEMPLATE(amd64_linux, sys_clone);
    357 DECL_TEMPLATE(amd64_linux, sys_rt_sigreturn);
    358 DECL_TEMPLATE(amd64_linux, sys_socket);
    359 DECL_TEMPLATE(amd64_linux, sys_setsockopt);
    360 DECL_TEMPLATE(amd64_linux, sys_getsockopt);
    361 DECL_TEMPLATE(amd64_linux, sys_connect);
    362 DECL_TEMPLATE(amd64_linux, sys_accept);
    363 DECL_TEMPLATE(amd64_linux, sys_accept4);
    364 DECL_TEMPLATE(amd64_linux, sys_sendto);
    365 DECL_TEMPLATE(amd64_linux, sys_recvfrom);
    366 DECL_TEMPLATE(amd64_linux, sys_sendmsg);
    367 DECL_TEMPLATE(amd64_linux, sys_recvmsg);
    368 DECL_TEMPLATE(amd64_linux, sys_shutdown);
    369 DECL_TEMPLATE(amd64_linux, sys_bind);
    370 DECL_TEMPLATE(amd64_linux, sys_listen);
    371 DECL_TEMPLATE(amd64_linux, sys_getsockname);
    372 DECL_TEMPLATE(amd64_linux, sys_getpeername);
    373 DECL_TEMPLATE(amd64_linux, sys_socketpair);
    374 DECL_TEMPLATE(amd64_linux, sys_semget);
    375 DECL_TEMPLATE(amd64_linux, sys_semop);
    376 DECL_TEMPLATE(amd64_linux, sys_semtimedop);
    377 DECL_TEMPLATE(amd64_linux, sys_semctl);
    378 DECL_TEMPLATE(amd64_linux, sys_msgget);
    379 DECL_TEMPLATE(amd64_linux, sys_msgrcv);
    380 DECL_TEMPLATE(amd64_linux, sys_msgsnd);
    381 DECL_TEMPLATE(amd64_linux, sys_msgctl);
    382 DECL_TEMPLATE(amd64_linux, sys_shmget);
    383 DECL_TEMPLATE(amd64_linux, wrap_sys_shmat);
    384 DECL_TEMPLATE(amd64_linux, sys_shmdt);
    385 DECL_TEMPLATE(amd64_linux, sys_shmdt);
    386 DECL_TEMPLATE(amd64_linux, sys_shmctl);
    387 DECL_TEMPLATE(amd64_linux, sys_arch_prctl);
    388 DECL_TEMPLATE(amd64_linux, sys_ptrace);
    389 DECL_TEMPLATE(amd64_linux, sys_fadvise64);
    390 DECL_TEMPLATE(amd64_linux, sys_mmap);
    391 DECL_TEMPLATE(amd64_linux, sys_syscall184);
    392 
    393 
    394 PRE(sys_clone)
    395 {
    396    ULong cloneflags;
    397 
    398    PRINT("sys_clone ( %lx, %#lx, %#lx, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4,ARG5);
    399    PRE_REG_READ5(int, "clone",
    400                  unsigned long, flags,
    401                  void *, child_stack,
    402                  int *, parent_tidptr,
    403                  int *, child_tidptr,
    404                  void *, tlsaddr);
    405 
    406    if (ARG1 & VKI_CLONE_PARENT_SETTID) {
    407       PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
    408       if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int), VKI_PROT_WRITE)) {
    409          SET_STATUS_Failure( VKI_EFAULT );
    410          return;
    411       }
    412    }
    413    if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
    414       PRE_MEM_WRITE("clone(child_tidptr)", ARG4, sizeof(Int));
    415       if (!VG_(am_is_valid_for_client)(ARG4, sizeof(Int), VKI_PROT_WRITE)) {
    416          SET_STATUS_Failure( VKI_EFAULT );
    417          return;
    418       }
    419    }
    420 
    421    cloneflags = ARG1;
    422 
    423    if (!ML_(client_signal_OK)(ARG1 & VKI_CSIGNAL)) {
    424       SET_STATUS_Failure( VKI_EINVAL );
    425       return;
    426    }
    427 
    428    /* Only look at the flags we really care about */
    429    switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS
    430                          | VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
    431    case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
    432       /* thread creation */
    433       SET_STATUS_from_SysRes(
    434          do_clone(tid,
    435                   ARG1,          /* flags */
    436                   (Addr)ARG2,    /* child ESP */
    437                   (Long *)ARG3,  /* parent_tidptr */
    438                   (Long *)ARG4,  /* child_tidptr */
    439                   (Addr)ARG5));  /* set_tls */
    440       break;
    441 
    442    case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
    443       /* FALLTHROUGH - assume vfork == fork */
    444       cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
    445 
    446    case 0: /* plain fork */
    447       SET_STATUS_from_SysRes(
    448          ML_(do_fork_clone)(tid,
    449                        cloneflags,      /* flags */
    450                        (Int *)ARG3,     /* parent_tidptr */
    451                        (Int *)ARG4));   /* child_tidptr */
    452       break;
    453 
    454    default:
    455       /* should we just ENOSYS? */
    456       VG_(message)(Vg_UserMsg,
    457                    "Unsupported clone() flags: 0x%lx\n", ARG1);
    458       VG_(message)(Vg_UserMsg,
    459                    "\n");
    460       VG_(message)(Vg_UserMsg,
    461                    "The only supported clone() uses are:\n");
    462       VG_(message)(Vg_UserMsg,
    463                    " - via a threads library (LinuxThreads or NPTL)\n");
    464       VG_(message)(Vg_UserMsg,
    465                    " - via the implementation of fork or vfork\n");
    466       VG_(unimplemented)
    467          ("Valgrind does not support general clone().");
    468    }
    469 
    470    if (SUCCESS) {
    471       if (ARG1 & VKI_CLONE_PARENT_SETTID)
    472          POST_MEM_WRITE(ARG3, sizeof(Int));
    473       if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID))
    474          POST_MEM_WRITE(ARG4, sizeof(Int));
    475 
    476       /* Thread creation was successful; let the child have the chance
    477          to run */
    478       *flags |= SfYieldAfter;
    479    }
    480 }
    481 
    482 PRE(sys_rt_sigreturn)
    483 {
    484    /* This isn't really a syscall at all - it's a misuse of the
    485       syscall mechanism by m_sigframe.  VG_(sigframe_create) sets the
    486       return address of the signal frames it creates to be a short
    487       piece of code which does this "syscall".  The only purpose of
    488       the syscall is to call VG_(sigframe_destroy), which restores the
    489       thread's registers from the frame and then removes it.
    490       Consequently we must ask the syswrap driver logic not to write
    491       back the syscall "result" as that would overwrite the
    492       just-restored register state. */
    493 
    494    ThreadState* tst;
    495    PRINT("sys_rt_sigreturn ( )");
    496 
    497    vg_assert(VG_(is_valid_tid)(tid));
    498    vg_assert(tid >= 1 && tid < VG_N_THREADS);
    499    vg_assert(VG_(is_running_thread)(tid));
    500 
    501    /* Adjust RSP to point to start of frame; skip back up over handler
    502       ret addr */
    503    tst = VG_(get_ThreadState)(tid);
    504    tst->arch.vex.guest_RSP -= sizeof(Addr);
    505 
    506    /* This is only so that the RIP is (might be) useful to report if
    507       something goes wrong in the sigreturn.  JRS 20070318: no idea
    508       what this is for */
    509    ML_(fixup_guest_state_to_restart_syscall)(&tst->arch);
    510 
    511    /* Restore register state from frame and remove it, as
    512       described above */
    513    VG_(sigframe_destroy)(tid, True);
    514 
    515    /* Tell the driver not to update the guest state with the "result",
    516       and set a bogus result to keep it happy. */
    517    *flags |= SfNoWriteResult;
    518    SET_STATUS_Success(0);
    519 
    520    /* Check to see if any signals arose as a result of this. */
    521    *flags |= SfPollAfter;
    522 }
    523 
    524 PRE(sys_arch_prctl)
    525 {
    526    ThreadState* tst;
    527    PRINT( "arch_prctl ( %ld, %lx )", ARG1, ARG2 );
    528 
    529    vg_assert(VG_(is_valid_tid)(tid));
    530    vg_assert(tid >= 1 && tid < VG_N_THREADS);
    531    vg_assert(VG_(is_running_thread)(tid));
    532 
    533    // Nb: can't use "ARG2".."ARG5" here because that's our own macro...
    534    PRE_REG_READ2(long, "arch_prctl",
    535                  int, option, unsigned long, arg2);
    536    // XXX: totally wrong... we need to look at the 'option' arg, and do
    537    // PRE_MEM_READs/PRE_MEM_WRITEs as necessary...
    538 
    539    /* "do" the syscall ourselves; the kernel never sees it */
    540    if (ARG1 == VKI_ARCH_SET_FS) {
    541       tst = VG_(get_ThreadState)(tid);
    542       tst->arch.vex.guest_FS_ZERO = ARG2;
    543    }
    544    else if (ARG1 == VKI_ARCH_GET_FS) {
    545       PRE_MEM_WRITE("arch_prctl(addr)", ARG2, sizeof(unsigned long));
    546       tst = VG_(get_ThreadState)(tid);
    547       *(unsigned long *)ARG2 = tst->arch.vex.guest_FS_ZERO;
    548       POST_MEM_WRITE(ARG2, sizeof(unsigned long));
    549    }
    550    else {
    551       VG_(core_panic)("Unsupported arch_prtctl option");
    552    }
    553 
    554    /* Note; the Status writeback to guest state that happens after
    555       this wrapper returns does not change guest_FS_ZERO; hence that
    556       direct assignment to the guest state is safe here. */
    557    SET_STATUS_Success( 0 );
    558 }
    559 
    560 // Parts of this are amd64-specific, but the *PEEK* cases are generic.
    561 //
    562 // ARG3 is only used for pointers into the traced process's address
    563 // space and for offsets into the traced process's struct
    564 // user_regs_struct. It is never a pointer into this process's memory
    565 // space, and we should therefore not check anything it points to.
    566 PRE(sys_ptrace)
    567 {
    568    PRINT("sys_ptrace ( %ld, %ld, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4);
    569    PRE_REG_READ4(int, "ptrace",
    570                  long, request, long, pid, long, addr, long, data);
    571    switch (ARG1) {
    572    case VKI_PTRACE_PEEKTEXT:
    573    case VKI_PTRACE_PEEKDATA:
    574    case VKI_PTRACE_PEEKUSR:
    575       PRE_MEM_WRITE( "ptrace(peek)", ARG4,
    576 		     sizeof (long));
    577       break;
    578    case VKI_PTRACE_GETREGS:
    579       PRE_MEM_WRITE( "ptrace(getregs)", ARG4,
    580 		     sizeof (struct vki_user_regs_struct));
    581       break;
    582    case VKI_PTRACE_GETFPREGS:
    583       PRE_MEM_WRITE( "ptrace(getfpregs)", ARG4,
    584 		     sizeof (struct vki_user_i387_struct));
    585       break;
    586    case VKI_PTRACE_SETREGS:
    587       PRE_MEM_READ( "ptrace(setregs)", ARG4,
    588 		     sizeof (struct vki_user_regs_struct));
    589       break;
    590    case VKI_PTRACE_SETFPREGS:
    591       PRE_MEM_READ( "ptrace(setfpregs)", ARG4,
    592 		     sizeof (struct vki_user_i387_struct));
    593       break;
    594    case VKI_PTRACE_GETEVENTMSG:
    595       PRE_MEM_WRITE( "ptrace(geteventmsg)", ARG4, sizeof(unsigned long));
    596       break;
    597    case VKI_PTRACE_GETSIGINFO:
    598       PRE_MEM_WRITE( "ptrace(getsiginfo)", ARG4, sizeof(vki_siginfo_t));
    599       break;
    600    case VKI_PTRACE_SETSIGINFO:
    601       PRE_MEM_READ( "ptrace(setsiginfo)", ARG4, sizeof(vki_siginfo_t));
    602       break;
    603    default:
    604       break;
    605    }
    606 }
    607 
    608 POST(sys_ptrace)
    609 {
    610    switch (ARG1) {
    611    case VKI_PTRACE_PEEKTEXT:
    612    case VKI_PTRACE_PEEKDATA:
    613    case VKI_PTRACE_PEEKUSR:
    614       POST_MEM_WRITE( ARG4, sizeof (long));
    615       break;
    616    case VKI_PTRACE_GETREGS:
    617       POST_MEM_WRITE( ARG4, sizeof (struct vki_user_regs_struct));
    618       break;
    619    case VKI_PTRACE_GETFPREGS:
    620       POST_MEM_WRITE( ARG4, sizeof (struct vki_user_i387_struct));
    621       break;
    622    case VKI_PTRACE_GETEVENTMSG:
    623       POST_MEM_WRITE( ARG4, sizeof(unsigned long));
    624       break;
    625    case VKI_PTRACE_GETSIGINFO:
    626       /* XXX: This is a simplification. Different parts of the
    627        * siginfo_t are valid depending on the type of signal.
    628        */
    629       POST_MEM_WRITE( ARG4, sizeof(vki_siginfo_t));
    630       break;
    631    default:
    632       break;
    633    }
    634 }
    635 
    636 PRE(sys_socket)
    637 {
    638    PRINT("sys_socket ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
    639    PRE_REG_READ3(long, "socket", int, domain, int, type, int, protocol);
    640 }
    641 POST(sys_socket)
    642 {
    643    SysRes r;
    644    vg_assert(SUCCESS);
    645    r = ML_(generic_POST_sys_socket)(tid, VG_(mk_SysRes_Success)(RES));
    646    SET_STATUS_from_SysRes(r);
    647 }
    648 
    649 PRE(sys_setsockopt)
    650 {
    651    PRINT("sys_setsockopt ( %ld, %ld, %ld, %#lx, %ld )",ARG1,ARG2,ARG3,ARG4,ARG5);
    652    PRE_REG_READ5(long, "setsockopt",
    653                  int, s, int, level, int, optname,
    654                  const void *, optval, int, optlen);
    655    ML_(generic_PRE_sys_setsockopt)(tid, ARG1,ARG2,ARG3,ARG4,ARG5);
    656 }
    657 
    658 PRE(sys_getsockopt)
    659 {
    660    PRINT("sys_getsockopt ( %ld, %ld, %ld, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4,ARG5);
    661    PRE_REG_READ5(long, "getsockopt",
    662                  int, s, int, level, int, optname,
    663                  void *, optval, int, *optlen);
    664    ML_(linux_PRE_sys_getsockopt)(tid, ARG1,ARG2,ARG3,ARG4,ARG5);
    665 }
    666 POST(sys_getsockopt)
    667 {
    668    vg_assert(SUCCESS);
    669    ML_(linux_POST_sys_getsockopt)(tid, VG_(mk_SysRes_Success)(RES),
    670                                        ARG1,ARG2,ARG3,ARG4,ARG5);
    671 }
    672 
    673 PRE(sys_connect)
    674 {
    675    *flags |= SfMayBlock;
    676    PRINT("sys_connect ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
    677    PRE_REG_READ3(long, "connect",
    678                  int, sockfd, struct sockaddr *, serv_addr, int, addrlen);
    679    ML_(generic_PRE_sys_connect)(tid, ARG1,ARG2,ARG3);
    680 }
    681 
    682 PRE(sys_accept)
    683 {
    684    *flags |= SfMayBlock;
    685    PRINT("sys_accept ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
    686    PRE_REG_READ3(long, "accept",
    687                  int, s, struct sockaddr *, addr, int, *addrlen);
    688    ML_(generic_PRE_sys_accept)(tid, ARG1,ARG2,ARG3);
    689 }
    690 POST(sys_accept)
    691 {
    692    SysRes r;
    693    vg_assert(SUCCESS);
    694    r = ML_(generic_POST_sys_accept)(tid, VG_(mk_SysRes_Success)(RES),
    695                                          ARG1,ARG2,ARG3);
    696    SET_STATUS_from_SysRes(r);
    697 }
    698 
    699 PRE(sys_accept4)
    700 {
    701    *flags |= SfMayBlock;
    702    PRINT("sys_accept4 ( %ld, %#lx, %ld, %ld )",ARG1,ARG2,ARG3,ARG4);
    703    PRE_REG_READ4(long, "accept4",
    704                  int, s, struct sockaddr *, addr, int, *addrlen, int, flags);
    705    ML_(generic_PRE_sys_accept)(tid, ARG1,ARG2,ARG3);
    706 }
    707 POST(sys_accept4)
    708 {
    709    SysRes r;
    710    vg_assert(SUCCESS);
    711    r = ML_(generic_POST_sys_accept)(tid, VG_(mk_SysRes_Success)(RES),
    712                                          ARG1,ARG2,ARG3);
    713    SET_STATUS_from_SysRes(r);
    714 }
    715 
    716 PRE(sys_sendto)
    717 {
    718    *flags |= SfMayBlock;
    719    PRINT("sys_sendto ( %ld, %#lx, %ld, %lu, %#lx, %ld )",ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
    720    PRE_REG_READ6(long, "sendto",
    721                  int, s, const void *, msg, int, len,
    722                  unsigned int, flags,
    723                  const struct sockaddr *, to, int, tolen);
    724    ML_(generic_PRE_sys_sendto)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
    725 }
    726 
    727 PRE(sys_recvfrom)
    728 {
    729    *flags |= SfMayBlock;
    730    PRINT("sys_recvfrom ( %ld, %#lx, %ld, %lu, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
    731    PRE_REG_READ6(long, "recvfrom",
    732                  int, s, void *, buf, int, len, unsigned int, flags,
    733                  struct sockaddr *, from, int *, fromlen);
    734    ML_(generic_PRE_sys_recvfrom)(tid, ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
    735 }
    736 POST(sys_recvfrom)
    737 {
    738    vg_assert(SUCCESS);
    739    ML_(generic_POST_sys_recvfrom)(tid, VG_(mk_SysRes_Success)(RES),
    740                                        ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
    741 }
    742 
    743 PRE(sys_sendmsg)
    744 {
    745    *flags |= SfMayBlock;
    746    PRINT("sys_sendmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
    747    PRE_REG_READ3(long, "sendmsg",
    748                  int, s, const struct msghdr *, msg, int, flags);
    749    ML_(generic_PRE_sys_sendmsg)(tid, ARG1,ARG2);
    750 }
    751 
    752 PRE(sys_recvmsg)
    753 {
    754    *flags |= SfMayBlock;
    755    PRINT("sys_recvmsg ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
    756    PRE_REG_READ3(long, "recvmsg", int, s, struct msghdr *, msg, int, flags);
    757    ML_(generic_PRE_sys_recvmsg)(tid, ARG1,ARG2);
    758 }
    759 POST(sys_recvmsg)
    760 {
    761    ML_(generic_POST_sys_recvmsg)(tid, ARG1,ARG2);
    762 }
    763 
    764 PRE(sys_shutdown)
    765 {
    766    *flags |= SfMayBlock;
    767    PRINT("sys_shutdown ( %ld, %ld )",ARG1,ARG2);
    768    PRE_REG_READ2(int, "shutdown", int, s, int, how);
    769 }
    770 
    771 PRE(sys_bind)
    772 {
    773    PRINT("sys_bind ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
    774    PRE_REG_READ3(long, "bind",
    775                  int, sockfd, struct sockaddr *, my_addr, int, addrlen);
    776    ML_(generic_PRE_sys_bind)(tid, ARG1,ARG2,ARG3);
    777 }
    778 
    779 PRE(sys_listen)
    780 {
    781    PRINT("sys_listen ( %ld, %ld )",ARG1,ARG2);
    782    PRE_REG_READ2(long, "listen", int, s, int, backlog);
    783 }
    784 
    785 PRE(sys_getsockname)
    786 {
    787    PRINT("sys_getsockname ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3);
    788    PRE_REG_READ3(long, "getsockname",
    789                  int, s, struct sockaddr *, name, int *, namelen);
    790    ML_(generic_PRE_sys_getsockname)(tid, ARG1,ARG2,ARG3);
    791 }
    792 POST(sys_getsockname)
    793 {
    794    vg_assert(SUCCESS);
    795    ML_(generic_POST_sys_getsockname)(tid, VG_(mk_SysRes_Success)(RES),
    796                                           ARG1,ARG2,ARG3);
    797 }
    798 
    799 PRE(sys_getpeername)
    800 {
    801    PRINT("sys_getpeername ( %ld, %#lx, %#lx )",ARG1,ARG2,ARG3);
    802    PRE_REG_READ3(long, "getpeername",
    803                  int, s, struct sockaddr *, name, int *, namelen);
    804    ML_(generic_PRE_sys_getpeername)(tid, ARG1,ARG2,ARG3);
    805 }
    806 POST(sys_getpeername)
    807 {
    808    vg_assert(SUCCESS);
    809    ML_(generic_POST_sys_getpeername)(tid, VG_(mk_SysRes_Success)(RES),
    810                                           ARG1,ARG2,ARG3);
    811 }
    812 
    813 PRE(sys_socketpair)
    814 {
    815    PRINT("sys_socketpair ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
    816    PRE_REG_READ4(long, "socketpair",
    817                  int, d, int, type, int, protocol, int*, sv);
    818    ML_(generic_PRE_sys_socketpair)(tid, ARG1,ARG2,ARG3,ARG4);
    819 }
    820 POST(sys_socketpair)
    821 {
    822    vg_assert(SUCCESS);
    823    ML_(generic_POST_sys_socketpair)(tid, VG_(mk_SysRes_Success)(RES),
    824                                          ARG1,ARG2,ARG3,ARG4);
    825 }
    826 
    827 PRE(sys_semget)
    828 {
    829    PRINT("sys_semget ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
    830    PRE_REG_READ3(long, "semget", vki_key_t, key, int, nsems, int, semflg);
    831 }
    832 
    833 PRE(sys_semop)
    834 {
    835    *flags |= SfMayBlock;
    836    PRINT("sys_semop ( %ld, %#lx, %lu )",ARG1,ARG2,ARG3);
    837    PRE_REG_READ3(long, "semop",
    838                  int, semid, struct sembuf *, sops, unsigned, nsoops);
    839    ML_(generic_PRE_sys_semop)(tid, ARG1,ARG2,ARG3);
    840 }
    841 
    842 PRE(sys_semtimedop)
    843 {
    844    *flags |= SfMayBlock;
    845    PRINT("sys_semtimedop ( %ld, %#lx, %lu, %#lx )",ARG1,ARG2,ARG3,ARG4);
    846    PRE_REG_READ4(long, "semtimedop",
    847                  int, semid, struct sembuf *, sops, unsigned, nsoops,
    848                  struct timespec *, timeout);
    849    ML_(generic_PRE_sys_semtimedop)(tid, ARG1,ARG2,ARG3,ARG4);
    850 }
    851 
    852 PRE(sys_semctl)
    853 {
    854    switch (ARG3 & ~VKI_IPC_64) {
    855    case VKI_IPC_INFO:
    856    case VKI_SEM_INFO:
    857       PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
    858       PRE_REG_READ4(long, "semctl",
    859                     int, semid, int, semnum, int, cmd, struct seminfo *, arg);
    860       break;
    861    case VKI_IPC_STAT:
    862    case VKI_SEM_STAT:
    863    case VKI_IPC_SET:
    864       PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
    865       PRE_REG_READ4(long, "semctl",
    866                     int, semid, int, semnum, int, cmd, struct semid_ds *, arg);
    867       break;
    868    case VKI_GETALL:
    869    case VKI_SETALL:
    870       PRINT("sys_semctl ( %ld, %ld, %ld, %#lx )",ARG1,ARG2,ARG3,ARG4);
    871       PRE_REG_READ4(long, "semctl",
    872                     int, semid, int, semnum, int, cmd, unsigned short *, arg);
    873       break;
    874    default:
    875       PRINT("sys_semctl ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
    876       PRE_REG_READ3(long, "semctl",
    877                     int, semid, int, semnum, int, cmd);
    878       break;
    879    }
    880    ML_(generic_PRE_sys_semctl)(tid, ARG1,ARG2,ARG3|VKI_IPC_64,ARG4);
    881 }
    882 POST(sys_semctl)
    883 {
    884    ML_(generic_POST_sys_semctl)(tid, RES,ARG1,ARG2,ARG3|VKI_IPC_64,ARG4);
    885 }
    886 
    887 PRE(sys_msgget)
    888 {
    889    PRINT("sys_msgget ( %ld, %ld )",ARG1,ARG2);
    890    PRE_REG_READ2(long, "msgget", vki_key_t, key, int, msgflg);
    891 }
    892 
    893 PRE(sys_msgsnd)
    894 {
    895    PRINT("sys_msgsnd ( %ld, %#lx, %ld, %ld )",ARG1,ARG2,ARG3,ARG4);
    896    PRE_REG_READ4(long, "msgsnd",
    897                  int, msqid, struct msgbuf *, msgp, vki_size_t, msgsz, int, msgflg);
    898    ML_(linux_PRE_sys_msgsnd)(tid, ARG1,ARG2,ARG3,ARG4);
    899    if ((ARG4 & VKI_IPC_NOWAIT) == 0)
    900       *flags |= SfMayBlock;
    901 }
    902 
    903 PRE(sys_msgrcv)
    904 {
    905    PRINT("sys_msgrcv ( %ld, %#lx, %ld, %ld, %ld )",ARG1,ARG2,ARG3,ARG4,ARG5);
    906    PRE_REG_READ5(long, "msgrcv",
    907                  int, msqid, struct msgbuf *, msgp, vki_size_t, msgsz,
    908                  long, msgytp, int, msgflg);
    909    ML_(linux_PRE_sys_msgrcv)(tid, ARG1,ARG2,ARG3,ARG4,ARG5);
    910    if ((ARG4 & VKI_IPC_NOWAIT) == 0)
    911       *flags |= SfMayBlock;
    912 }
    913 POST(sys_msgrcv)
    914 {
    915    ML_(linux_POST_sys_msgrcv)(tid, RES,ARG1,ARG2,ARG3,ARG4,ARG5);
    916 }
    917 
    918 PRE(sys_msgctl)
    919 {
    920    PRINT("sys_msgctl ( %ld, %ld, %#lx )",ARG1,ARG2,ARG3);
    921    PRE_REG_READ3(long, "msgctl",
    922                  int, msqid, int, cmd, struct msqid_ds *, buf);
    923    ML_(linux_PRE_sys_msgctl)(tid, ARG1,ARG2,ARG3);
    924 }
    925 POST(sys_msgctl)
    926 {
    927    ML_(linux_POST_sys_msgctl)(tid, RES,ARG1,ARG2,ARG3);
    928 }
    929 
    930 PRE(sys_shmget)
    931 {
    932    PRINT("sys_shmget ( %ld, %ld, %ld )",ARG1,ARG2,ARG3);
    933    PRE_REG_READ3(long, "shmget", vki_key_t, key, vki_size_t, size, int, shmflg);
    934 }
    935 
    936 PRE(wrap_sys_shmat)
    937 {
    938    UWord arg2tmp;
    939    PRINT("wrap_sys_shmat ( %ld, %#lx, %ld )",ARG1,ARG2,ARG3);
    940    PRE_REG_READ3(long, "shmat",
    941                  int, shmid, const void *, shmaddr, int, shmflg);
    942    arg2tmp = ML_(generic_PRE_sys_shmat)(tid, ARG1,ARG2,ARG3);
    943    if (arg2tmp == 0)
    944       SET_STATUS_Failure( VKI_EINVAL );
    945    else
    946       ARG2 = arg2tmp;  // used in POST
    947 }
    948 POST(wrap_sys_shmat)
    949 {
    950    ML_(generic_POST_sys_shmat)(tid, RES,ARG1,ARG2,ARG3);
    951 }
    952 
    953 PRE(sys_shmdt)
    954 {
    955    PRINT("sys_shmdt ( %#lx )",ARG1);
    956    PRE_REG_READ1(long, "shmdt", const void *, shmaddr);
    957    if (!ML_(generic_PRE_sys_shmdt)(tid, ARG1))
    958       SET_STATUS_Failure( VKI_EINVAL );
    959 }
    960 POST(sys_shmdt)
    961 {
    962    ML_(generic_POST_sys_shmdt)(tid, RES,ARG1);
    963 }
    964 
    965 PRE(sys_shmctl)
    966 {
    967    PRINT("sys_shmctl ( %ld, %ld, %#lx )",ARG1,ARG2,ARG3);
    968    PRE_REG_READ3(long, "shmctl",
    969                  int, shmid, int, cmd, struct shmid_ds *, buf);
    970    ML_(generic_PRE_sys_shmctl)(tid, ARG1,ARG2|VKI_IPC_64,ARG3);
    971 }
    972 POST(sys_shmctl)
    973 {
    974    ML_(generic_POST_sys_shmctl)(tid, RES,ARG1,ARG2|VKI_IPC_64,ARG3);
    975 }
    976 
    977 PRE(sys_fadvise64)
    978 {
    979    PRINT("sys_fadvise64 ( %ld, %ld, %lu, %ld )", ARG1,ARG2,ARG3,ARG4);
    980    PRE_REG_READ4(long, "fadvise64",
    981                  int, fd, vki_loff_t, offset, vki_size_t, len, int, advice);
    982 }
    983 
    984 PRE(sys_mmap)
    985 {
    986    SysRes r;
    987 
    988    PRINT("sys_mmap ( %#lx, %llu, %ld, %ld, %d, %ld )",
    989          ARG1, (ULong)ARG2, ARG3, ARG4, (Int)ARG5, ARG6 );
    990    PRE_REG_READ6(long, "mmap",
    991                  unsigned long, start, unsigned long, length,
    992                  unsigned long, prot,  unsigned long, flags,
    993                  unsigned long, fd,    unsigned long, offset);
    994 
    995    r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
    996    SET_STATUS_from_SysRes(r);
    997 }
    998 
    999 
   1000 /* ---------------------------------------------------------------
   1001    PRE/POST wrappers for AMD64/Linux-variant specific syscalls
   1002    ------------------------------------------------------------ */
   1003 
   1004 PRE(sys_syscall184)
   1005 {
   1006    Int err;
   1007 
   1008    /* 184 is used by sys_bproc.  If we're not on a declared bproc
   1009       variant, fail in the usual way, since it is otherwise unused. */
   1010 
   1011    if (!VG_(strstr)(VG_(clo_kernel_variant), "bproc")) {
   1012       PRINT("non-existent syscall! (syscall 184)");
   1013       PRE_REG_READ0(long, "ni_syscall(184)");
   1014       SET_STATUS_Failure( VKI_ENOSYS );
   1015       return;
   1016    }
   1017 
   1018    err = ML_(linux_variant_PRE_sys_bproc)( ARG1, ARG2, ARG3,
   1019                                            ARG4, ARG5, ARG6 );
   1020    if (err) {
   1021       SET_STATUS_Failure( err );
   1022       return;
   1023    }
   1024    /* Let it go through. */
   1025    *flags |= SfMayBlock; /* who knows?  play safe. */
   1026 }
   1027 
   1028 POST(sys_syscall184)
   1029 {
   1030    ML_(linux_variant_POST_sys_bproc)( ARG1, ARG2, ARG3,
   1031                                       ARG4, ARG5, ARG6 );
   1032 }
   1033 
   1034 #undef PRE
   1035 #undef POST
   1036 
   1037 
   1038 /* ---------------------------------------------------------------------
   1039    The AMD64/Linux syscall table
   1040    ------------------------------------------------------------------ */
   1041 
   1042 /* Add an amd64-linux specific wrapper to a syscall table. */
   1043 #define PLAX_(const, name)    WRAPPER_ENTRY_X_(amd64_linux, const, name)
   1044 #define PLAXY(const, name)    WRAPPER_ENTRY_XY(amd64_linux, const, name)
   1045 
   1046 // This table maps from __NR_xxx syscall numbers (from
   1047 // linux/include/asm-x86_64/unistd.h) to the appropriate PRE/POST sys_foo()
   1048 // wrappers on AMD64 (as per sys_call_table in
   1049 // linux/arch/x86_64/kernel/entry.S).
   1050 //
   1051 // When implementing these wrappers, you need to work out if the wrapper is
   1052 // generic, Linux-only (but arch-independent), or AMD64/Linux only.
   1053 
   1054 static SyscallTableEntry syscall_table[] = {
   1055    GENXY(__NR_read,              sys_read),           // 0
   1056    GENX_(__NR_write,             sys_write),          // 1
   1057    GENXY(__NR_open,              sys_open),           // 2
   1058    GENXY(__NR_close,             sys_close),          // 3
   1059    GENXY(__NR_stat,              sys_newstat),        // 4
   1060 
   1061    GENXY(__NR_fstat,             sys_newfstat),       // 5
   1062    GENXY(__NR_lstat,             sys_newlstat),       // 6
   1063    GENXY(__NR_poll,              sys_poll),           // 7
   1064    LINX_(__NR_lseek,             sys_lseek),          // 8
   1065    PLAX_(__NR_mmap,              sys_mmap),           // 9
   1066 
   1067    GENXY(__NR_mprotect,          sys_mprotect),       // 10
   1068    GENXY(__NR_munmap,            sys_munmap),         // 11
   1069    GENX_(__NR_brk,               sys_brk),            // 12
   1070    LINXY(__NR_rt_sigaction,      sys_rt_sigaction),   // 13
   1071    LINXY(__NR_rt_sigprocmask,    sys_rt_sigprocmask), // 14
   1072 
   1073    PLAX_(__NR_rt_sigreturn,      sys_rt_sigreturn),   // 15
   1074    LINXY(__NR_ioctl,             sys_ioctl),          // 16
   1075    GENXY(__NR_pread64,           sys_pread64),        // 17
   1076    GENX_(__NR_pwrite64,          sys_pwrite64),       // 18
   1077    GENXY(__NR_readv,             sys_readv),          // 19
   1078 
   1079    GENX_(__NR_writev,            sys_writev),         // 20
   1080    GENX_(__NR_access,            sys_access),         // 21
   1081    LINXY(__NR_pipe,              sys_pipe),           // 22
   1082    GENX_(__NR_select,            sys_select),         // 23
   1083    LINX_(__NR_sched_yield,       sys_sched_yield),    // 24
   1084 
   1085    GENX_(__NR_mremap,            sys_mremap),         // 25
   1086    GENX_(__NR_msync,             sys_msync),          // 26
   1087    GENX_(__NR_mincore,           sys_mincore),        // 27
   1088    GENX_(__NR_madvise,           sys_madvise),        // 28
   1089    PLAX_(__NR_shmget,            sys_shmget),         // 29
   1090 
   1091    PLAXY(__NR_shmat,             wrap_sys_shmat),     // 30
   1092    PLAXY(__NR_shmctl,            sys_shmctl),         // 31
   1093    GENXY(__NR_dup,               sys_dup),            // 32
   1094    GENXY(__NR_dup2,              sys_dup2),           // 33
   1095    GENX_(__NR_pause,             sys_pause),          // 34
   1096 
   1097    GENXY(__NR_nanosleep,         sys_nanosleep),      // 35
   1098    GENXY(__NR_getitimer,         sys_getitimer),      // 36
   1099    GENX_(__NR_alarm,             sys_alarm),          // 37
   1100    GENXY(__NR_setitimer,         sys_setitimer),      // 38
   1101    GENX_(__NR_getpid,            sys_getpid),         // 39
   1102 
   1103    LINXY(__NR_sendfile,          sys_sendfile),       // 40
   1104    PLAXY(__NR_socket,            sys_socket),         // 41
   1105    PLAX_(__NR_connect,           sys_connect),        // 42
   1106    PLAXY(__NR_accept,            sys_accept),         // 43
   1107    PLAX_(__NR_sendto,            sys_sendto),         // 44
   1108 
   1109    PLAXY(__NR_recvfrom,          sys_recvfrom),       // 45
   1110    PLAX_(__NR_sendmsg,           sys_sendmsg),        // 46
   1111    PLAXY(__NR_recvmsg,           sys_recvmsg),        // 47
   1112    PLAX_(__NR_shutdown,          sys_shutdown),       // 48
   1113    PLAX_(__NR_bind,              sys_bind),           // 49
   1114 
   1115    PLAX_(__NR_listen,            sys_listen),         // 50
   1116    PLAXY(__NR_getsockname,       sys_getsockname),    // 51
   1117    PLAXY(__NR_getpeername,       sys_getpeername),    // 52
   1118    PLAXY(__NR_socketpair,        sys_socketpair),     // 53
   1119    PLAX_(__NR_setsockopt,        sys_setsockopt),     // 54
   1120 
   1121    PLAXY(__NR_getsockopt,        sys_getsockopt),     // 55
   1122    PLAX_(__NR_clone,             sys_clone),          // 56
   1123    GENX_(__NR_fork,              sys_fork),           // 57
   1124    GENX_(__NR_vfork,             sys_fork),           // 58 treat as fork
   1125    GENX_(__NR_execve,            sys_execve),         // 59
   1126 
   1127    GENX_(__NR_exit,              sys_exit),           // 60
   1128    GENXY(__NR_wait4,             sys_wait4),          // 61
   1129    GENX_(__NR_kill,              sys_kill),           // 62
   1130    GENXY(__NR_uname,             sys_newuname),       // 63
   1131    PLAX_(__NR_semget,            sys_semget),         // 64
   1132 
   1133    PLAX_(__NR_semop,             sys_semop),          // 65
   1134    PLAXY(__NR_semctl,            sys_semctl),         // 66
   1135    PLAXY(__NR_shmdt,             sys_shmdt),          // 67
   1136    PLAX_(__NR_msgget,            sys_msgget),         // 68
   1137    PLAX_(__NR_msgsnd,            sys_msgsnd),         // 69
   1138 
   1139    PLAXY(__NR_msgrcv,            sys_msgrcv),         // 70
   1140    PLAXY(__NR_msgctl,            sys_msgctl),         // 71
   1141    LINXY(__NR_fcntl,             sys_fcntl),          // 72
   1142    GENX_(__NR_flock,             sys_flock),          // 73
   1143    GENX_(__NR_fsync,             sys_fsync),          // 74
   1144 
   1145    GENX_(__NR_fdatasync,         sys_fdatasync),      // 75
   1146    GENX_(__NR_truncate,          sys_truncate),       // 76
   1147    GENX_(__NR_ftruncate,         sys_ftruncate),      // 77
   1148    GENXY(__NR_getdents,          sys_getdents),       // 78
   1149    GENXY(__NR_getcwd,            sys_getcwd),         // 79
   1150 
   1151    GENX_(__NR_chdir,             sys_chdir),          // 80
   1152    GENX_(__NR_fchdir,            sys_fchdir),         // 81
   1153    GENX_(__NR_rename,            sys_rename),         // 82
   1154    GENX_(__NR_mkdir,             sys_mkdir),          // 83
   1155    GENX_(__NR_rmdir,             sys_rmdir),          // 84
   1156 
   1157    GENXY(__NR_creat,             sys_creat),          // 85
   1158    GENX_(__NR_link,              sys_link),           // 86
   1159    GENX_(__NR_unlink,            sys_unlink),         // 87
   1160    GENX_(__NR_symlink,           sys_symlink),        // 88
   1161    GENX_(__NR_readlink,          sys_readlink),       // 89
   1162 
   1163    GENX_(__NR_chmod,             sys_chmod),          // 90
   1164    GENX_(__NR_fchmod,            sys_fchmod),         // 91
   1165    GENX_(__NR_chown,             sys_chown),          // 92
   1166    GENX_(__NR_fchown,            sys_fchown),         // 93
   1167    GENX_(__NR_lchown,            sys_lchown),         // 94
   1168 
   1169    GENX_(__NR_umask,             sys_umask),          // 95
   1170    GENXY(__NR_gettimeofday,      sys_gettimeofday),   // 96
   1171    GENXY(__NR_getrlimit,         sys_getrlimit),      // 97
   1172    GENXY(__NR_getrusage,         sys_getrusage),      // 98
   1173    LINXY(__NR_sysinfo,           sys_sysinfo),        // 99
   1174 
   1175    GENXY(__NR_times,             sys_times),          // 100
   1176    PLAXY(__NR_ptrace,            sys_ptrace),         // 101
   1177    GENX_(__NR_getuid,            sys_getuid),         // 102
   1178    LINXY(__NR_syslog,            sys_syslog),         // 103
   1179    GENX_(__NR_getgid,            sys_getgid),         // 104
   1180 
   1181    GENX_(__NR_setuid,            sys_setuid),         // 105
   1182    GENX_(__NR_setgid,            sys_setgid),         // 106
   1183    GENX_(__NR_geteuid,           sys_geteuid),        // 107
   1184    GENX_(__NR_getegid,           sys_getegid),        // 108
   1185    GENX_(__NR_setpgid,           sys_setpgid),        // 109
   1186 
   1187    GENX_(__NR_getppid,           sys_getppid),        // 110
   1188    GENX_(__NR_getpgrp,           sys_getpgrp),        // 111
   1189    GENX_(__NR_setsid,            sys_setsid),         // 112
   1190    GENX_(__NR_setreuid,          sys_setreuid),       // 113
   1191    GENX_(__NR_setregid,          sys_setregid),       // 114
   1192 
   1193    GENXY(__NR_getgroups,         sys_getgroups),      // 115
   1194    GENX_(__NR_setgroups,         sys_setgroups),      // 116
   1195    LINX_(__NR_setresuid,         sys_setresuid),      // 117
   1196    LINXY(__NR_getresuid,         sys_getresuid),      // 118
   1197    LINX_(__NR_setresgid,         sys_setresgid),      // 119
   1198 
   1199    LINXY(__NR_getresgid,         sys_getresgid),      // 120
   1200    GENX_(__NR_getpgid,           sys_getpgid),        // 121
   1201    LINX_(__NR_setfsuid,          sys_setfsuid),       // 122
   1202    LINX_(__NR_setfsgid,          sys_setfsgid),       // 123
   1203    GENX_(__NR_getsid,            sys_getsid),         // 124
   1204 
   1205    LINXY(__NR_capget,            sys_capget),         // 125
   1206    LINX_(__NR_capset,            sys_capset),         // 126
   1207    LINXY(__NR_rt_sigpending,     sys_rt_sigpending),  // 127
   1208    LINXY(__NR_rt_sigtimedwait,   sys_rt_sigtimedwait),// 128
   1209    LINXY(__NR_rt_sigqueueinfo,   sys_rt_sigqueueinfo),// 129
   1210 
   1211    LINX_(__NR_rt_sigsuspend,     sys_rt_sigsuspend),  // 130
   1212    GENXY(__NR_sigaltstack,       sys_sigaltstack),    // 131
   1213    LINX_(__NR_utime,             sys_utime),          // 132
   1214    GENX_(__NR_mknod,             sys_mknod),          // 133
   1215    //   (__NR_uselib,            sys_uselib),         // 134
   1216 
   1217    LINX_(__NR_personality,       sys_personality),    // 135
   1218    //   (__NR_ustat,             sys_ustat),          // 136
   1219    GENXY(__NR_statfs,            sys_statfs),         // 137
   1220    GENXY(__NR_fstatfs,           sys_fstatfs),        // 138
   1221    //   (__NR_sysfs,             sys_sysfs),          // 139
   1222 
   1223    GENX_(__NR_getpriority,             sys_getpriority),             // 140
   1224    GENX_(__NR_setpriority,             sys_setpriority),             // 141
   1225    LINXY(__NR_sched_setparam,          sys_sched_setparam),          // 142
   1226    LINXY(__NR_sched_getparam,          sys_sched_getparam),          // 143
   1227    LINX_(__NR_sched_setscheduler,      sys_sched_setscheduler),      // 144
   1228 
   1229    LINX_(__NR_sched_getscheduler,      sys_sched_getscheduler),      // 145
   1230    LINX_(__NR_sched_get_priority_max,  sys_sched_get_priority_max),  // 146
   1231    LINX_(__NR_sched_get_priority_min,  sys_sched_get_priority_min),  // 147
   1232    LINXY(__NR_sched_rr_get_interval,   sys_sched_rr_get_interval),   // 148
   1233    GENX_(__NR_mlock,                   sys_mlock),                   // 149
   1234 
   1235    GENX_(__NR_munlock,           sys_munlock),        // 150
   1236    GENX_(__NR_mlockall,          sys_mlockall),       // 151
   1237    LINX_(__NR_munlockall,        sys_munlockall),     // 152
   1238    LINX_(__NR_vhangup,           sys_vhangup),        // 153
   1239    //   (__NR_modify_ldt,        sys_modify_ldt),     // 154
   1240 
   1241    //   (__NR_pivot_root,        sys_pivot_root),     // 155
   1242    LINXY(__NR__sysctl,           sys_sysctl),         // 156
   1243    LINXY(__NR_prctl,             sys_prctl),          // 157
   1244    PLAX_(__NR_arch_prctl,	 sys_arch_prctl),     // 158
   1245    LINXY(__NR_adjtimex,          sys_adjtimex),       // 159
   1246 
   1247    GENX_(__NR_setrlimit,         sys_setrlimit),      // 160
   1248    GENX_(__NR_chroot,            sys_chroot),         // 161
   1249    GENX_(__NR_sync,              sys_sync),           // 162
   1250    //   (__NR_acct,              sys_acct),           // 163
   1251    GENX_(__NR_settimeofday,      sys_settimeofday),   // 164
   1252 
   1253    LINX_(__NR_mount,             sys_mount),          // 165
   1254    LINX_(__NR_umount2,           sys_umount),         // 166
   1255    //   (__NR_swapon,            sys_swapon),         // 167
   1256    //   (__NR_swapoff,           sys_swapoff),        // 168
   1257    //   (__NR_reboot,            sys_reboot),         // 169
   1258 
   1259    //   (__NR_sethostname,       sys_sethostname),    // 170
   1260    //   (__NR_setdomainname,     sys_setdomainname),  // 171
   1261    GENX_(__NR_iopl,              sys_iopl),           // 172
   1262    LINX_(__NR_ioperm,            sys_ioperm),         // 173
   1263    GENX_(__NR_create_module,     sys_ni_syscall),     // 174
   1264 
   1265    LINX_(__NR_init_module,       sys_init_module),    // 175
   1266    LINX_(__NR_delete_module,     sys_delete_module),  // 176
   1267    //   (__NR_get_kernel_syms,   sys_ni_syscall),     // 177
   1268    //   (__NR_query_module,      sys_ni_syscall),     // 178
   1269    LINX_(__NR_quotactl,          sys_quotactl),       // 179
   1270 
   1271    //   (__NR_nfsservctl,        sys_nfsservctl),     // 180
   1272    //   (__NR_getpmsg,           sys_ni_syscall),     // 181
   1273    //   (__NR_putpmsg,           sys_ni_syscall),     // 182
   1274    //   (__NR_afs_syscall,       sys_ni_syscall),     // 183
   1275    PLAXY(184,                    sys_syscall184),     // 184 // sys_bproc?
   1276 
   1277    //   (__NR_security,          sys_ni_syscall),     // 185
   1278    LINX_(__NR_gettid,            sys_gettid),         // 186
   1279    LINX_(__NR_readahead,         sys_readahead),      // 187
   1280    LINX_(__NR_setxattr,          sys_setxattr),       // 188
   1281    LINX_(__NR_lsetxattr,         sys_lsetxattr),      // 189
   1282 
   1283    LINX_(__NR_fsetxattr,         sys_fsetxattr),      // 190
   1284    LINXY(__NR_getxattr,          sys_getxattr),       // 191
   1285    LINXY(__NR_lgetxattr,         sys_lgetxattr),      // 192
   1286    LINXY(__NR_fgetxattr,         sys_fgetxattr),      // 193
   1287    LINXY(__NR_listxattr,         sys_listxattr),      // 194
   1288 
   1289    LINXY(__NR_llistxattr,        sys_llistxattr),     // 195
   1290    LINXY(__NR_flistxattr,        sys_flistxattr),     // 196
   1291    LINX_(__NR_removexattr,       sys_removexattr),    // 197
   1292    LINX_(__NR_lremovexattr,      sys_lremovexattr),   // 198
   1293    LINX_(__NR_fremovexattr,      sys_fremovexattr),   // 199
   1294 
   1295    LINXY(__NR_tkill,             sys_tkill),             // 200
   1296    GENXY(__NR_time,              sys_time), /*was sys_time64*/ // 201
   1297    LINXY(__NR_futex,             sys_futex),             // 202
   1298    LINX_(__NR_sched_setaffinity, sys_sched_setaffinity), // 203
   1299    LINXY(__NR_sched_getaffinity, sys_sched_getaffinity), // 204
   1300 
   1301    //   (__NR_set_thread_area,   sys_ni_syscall),     // 205
   1302    LINXY(__NR_io_setup,          sys_io_setup),       // 206
   1303    LINX_(__NR_io_destroy,        sys_io_destroy),     // 207
   1304    LINXY(__NR_io_getevents,      sys_io_getevents),   // 208
   1305    LINX_(__NR_io_submit,         sys_io_submit),      // 209
   1306 
   1307    LINXY(__NR_io_cancel,         sys_io_cancel),      // 210
   1308    //   (__NR_get_thread_area,   sys_ni_syscall),     // 211
   1309    LINXY(__NR_lookup_dcookie,    sys_lookup_dcookie), // 212
   1310    LINXY(__NR_epoll_create,      sys_epoll_create),   // 213
   1311    //   (__NR_epoll_ctl_old,     sys_ni_syscall),     // 214
   1312 
   1313    //   (__NR_epoll_wait_old,    sys_ni_syscall),     // 215
   1314    //   (__NR_remap_file_pages,  sys_remap_file_pages)// 216
   1315    GENXY(__NR_getdents64,        sys_getdents64),     // 217
   1316    LINX_(__NR_set_tid_address,   sys_set_tid_address),// 218
   1317    //   (__NR_restart_syscall,   sys_restart_syscall),// 219
   1318 
   1319    PLAX_(__NR_semtimedop,        sys_semtimedop),     // 220
   1320    PLAX_(__NR_fadvise64,         sys_fadvise64),      // 221
   1321    LINXY(__NR_timer_create,      sys_timer_create),   // 222
   1322    LINXY(__NR_timer_settime,     sys_timer_settime),  // 223
   1323    LINXY(__NR_timer_gettime,     sys_timer_gettime),  // 224
   1324 
   1325    LINX_(__NR_timer_getoverrun,  sys_timer_getoverrun), // 225
   1326    LINX_(__NR_timer_delete,      sys_timer_delete),   // 226
   1327    LINX_(__NR_clock_settime,     sys_clock_settime),  // 227
   1328    LINXY(__NR_clock_gettime,     sys_clock_gettime),  // 228
   1329    LINXY(__NR_clock_getres,      sys_clock_getres),   // 229
   1330 
   1331    LINXY(__NR_clock_nanosleep,   sys_clock_nanosleep),// 230
   1332    LINX_(__NR_exit_group,        sys_exit_group),     // 231
   1333    LINXY(__NR_epoll_wait,        sys_epoll_wait),     // 232
   1334    LINX_(__NR_epoll_ctl,         sys_epoll_ctl),      // 233
   1335    LINXY(__NR_tgkill,            sys_tgkill),         // 234
   1336 
   1337    GENX_(__NR_utimes,            sys_utimes),         // 235
   1338    //   (__NR_vserver,           sys_ni_syscall),     // 236
   1339    LINX_(__NR_mbind,             sys_mbind),          // 237
   1340    LINX_(__NR_set_mempolicy,     sys_set_mempolicy),  // 238
   1341    LINXY(__NR_get_mempolicy,     sys_get_mempolicy),  // 239
   1342 
   1343    LINXY(__NR_mq_open,           sys_mq_open),        // 240
   1344    LINX_(__NR_mq_unlink,         sys_mq_unlink),      // 241
   1345    LINX_(__NR_mq_timedsend,      sys_mq_timedsend),   // 242
   1346    LINXY(__NR_mq_timedreceive,   sys_mq_timedreceive),// 243
   1347    LINX_(__NR_mq_notify,         sys_mq_notify),      // 244
   1348 
   1349    LINXY(__NR_mq_getsetattr,     sys_mq_getsetattr),  // 245
   1350    //   (__NR_kexec_load,        sys_ni_syscall),     // 246
   1351    LINXY(__NR_waitid,            sys_waitid),         // 247
   1352    LINX_(__NR_add_key,           sys_add_key),        // 248
   1353    LINX_(__NR_request_key,       sys_request_key),    // 249
   1354 
   1355    LINXY(__NR_keyctl,            sys_keyctl),         // 250
   1356    LINX_(__NR_ioprio_set,        sys_ioprio_set),     // 251
   1357    LINX_(__NR_ioprio_get,        sys_ioprio_get),     // 252
   1358    LINX_(__NR_inotify_init,	 sys_inotify_init),   // 253
   1359    LINX_(__NR_inotify_add_watch, sys_inotify_add_watch), // 254
   1360 
   1361    LINX_(__NR_inotify_rm_watch,	 sys_inotify_rm_watch), // 255
   1362 //   LINX_(__NR_migrate_pages,	 sys_migrate_pages),    // 256
   1363    LINXY(__NR_openat,		 sys_openat),           // 257
   1364    LINX_(__NR_mkdirat,		 sys_mkdirat),          // 258
   1365    LINX_(__NR_mknodat,		 sys_mknodat),          // 259
   1366 
   1367    LINX_(__NR_fchownat,		 sys_fchownat),         // 260
   1368    LINX_(__NR_futimesat,	 sys_futimesat),        // 261
   1369    LINXY(__NR_newfstatat,	 sys_newfstatat),       // 262
   1370    LINX_(__NR_unlinkat,		 sys_unlinkat),         // 263
   1371    LINX_(__NR_renameat,		 sys_renameat),         // 264
   1372 
   1373    LINX_(__NR_linkat,		 sys_linkat),           // 265
   1374    LINX_(__NR_symlinkat,	 sys_symlinkat),        // 266
   1375    LINX_(__NR_readlinkat,	 sys_readlinkat),       // 267
   1376    LINX_(__NR_fchmodat,		 sys_fchmodat),         // 268
   1377    LINX_(__NR_faccessat,	 sys_faccessat),        // 269
   1378 
   1379    LINX_(__NR_pselect6,		 sys_pselect6),         // 270
   1380    LINXY(__NR_ppoll,		 sys_ppoll),            // 271
   1381 //   LINX_(__NR_unshare,		 sys_unshare),          // 272
   1382    LINX_(__NR_set_robust_list,	 sys_set_robust_list),  // 273
   1383    LINXY(__NR_get_robust_list,	 sys_get_robust_list),  // 274
   1384 
   1385    LINX_(__NR_splice,            sys_splice),           // 275
   1386 //   LINX_(__NR_tee,               sys_ni_syscall),       // 276
   1387    LINX_(__NR_sync_file_range,   sys_sync_file_range),  // 277
   1388 //   LINX_(__NR_vmsplice,          sys_ni_syscall),       // 278
   1389 //   LINX_(__NR_move_pages,        sys_ni_syscall),       // 279
   1390 
   1391    LINX_(__NR_utimensat,         sys_utimensat),        // 280
   1392    LINXY(__NR_epoll_pwait,       sys_epoll_pwait),      // 281
   1393    LINXY(__NR_signalfd,          sys_signalfd),         // 282
   1394    LINXY(__NR_timerfd_create,    sys_timerfd_create),   // 283
   1395    LINX_(__NR_eventfd,           sys_eventfd),          // 284
   1396 
   1397    LINX_(__NR_fallocate,         sys_fallocate),        // 285
   1398    LINXY(__NR_timerfd_settime,   sys_timerfd_settime),  // 286
   1399    LINXY(__NR_timerfd_gettime,   sys_timerfd_gettime),  // 287
   1400    PLAXY(__NR_accept4,           sys_accept4),          // 288
   1401    LINXY(__NR_signalfd4,         sys_signalfd4),        // 289
   1402 
   1403    LINX_(__NR_eventfd2,          sys_eventfd2),         // 290
   1404    LINXY(__NR_epoll_create1,     sys_epoll_create1),    // 291
   1405    LINXY(__NR_dup3,              sys_dup3),             // 292
   1406    LINXY(__NR_pipe2,             sys_pipe2),            // 293
   1407    LINXY(__NR_inotify_init1,     sys_inotify_init1),    // 294
   1408 
   1409    LINXY(__NR_preadv,            sys_preadv),           // 295
   1410    LINX_(__NR_pwritev,           sys_pwritev),          // 296
   1411    LINXY(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo),// 297
   1412    LINXY(__NR_perf_counter_open, sys_perf_counter_open) // 298
   1413 };
   1414 
   1415 SyscallTableEntry* ML_(get_linux_syscall_entry) ( UInt sysno )
   1416 {
   1417    const UInt syscall_table_size
   1418       = sizeof(syscall_table) / sizeof(syscall_table[0]);
   1419 
   1420    /* Is it in the contiguous initial section of the table? */
   1421    if (sysno < syscall_table_size) {
   1422       SyscallTableEntry* sys = &syscall_table[sysno];
   1423       if (sys->before == NULL)
   1424          return NULL; /* no entry */
   1425       else
   1426          return sys;
   1427    }
   1428 
   1429    /* Can't find a wrapper */
   1430    return NULL;
   1431 }
   1432 
   1433 #endif // defined(VGP_amd64_linux)
   1434 
   1435 /*--------------------------------------------------------------------*/
   1436 /*--- end                                                          ---*/
   1437 /*--------------------------------------------------------------------*/
   1438