syswrap-x86-linux.c revision d140cf361ba12f3084fbe4a06e8f1a5500bd2285
1ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
3ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- Platform-specific syscalls stuff.        syswrap-x86-linux.c ---*/
4ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
5ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
6ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
7ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This file is part of Valgrind, a dynamic binary instrumentation
8ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   framework.
9ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
10ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Copyright (C) 2000-2010 Nicholas Nethercote
11ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      njn@valgrind.org
12ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
13ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is free software; you can redistribute it and/or
14ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify it under the terms of the GNU General Public License as
15ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   published by the Free Software Foundation; either version 2 of the
16ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   License, or (at your option) any later version.
17ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
18ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   This program is distributed in the hope that it will be useful, but
19ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   WITHOUT ANY WARRANTY; without even the implied warranty of
20ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   General Public License for more details.
22ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
23ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   You should have received a copy of the GNU General Public License
24ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   along with this program; if not, write to the Free Software
25ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   02111-1307, USA.
27ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
28ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The GNU General Public License is contained in the file COPYING.
29ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
30ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
31ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#if defined(VGP_x86_linux)
32ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
33ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* TODO/FIXME jrs 20050207: assignments to the syscall return result
34ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   in interrupted_syscall() need to be reviewed.  They don't seem
35ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   to assign the shadow state.
36ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
37ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
38ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_basics.h"
39ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vki.h"
40ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_vkiscnums.h"
41ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_threadstate.h"
42ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_aspacemgr.h"
43ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_debuglog.h"
44ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcbase.h"
45ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcassert.h"
46ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcprint.h"
47ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcproc.h"
48ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_libcsignal.h"
49ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_mallocfree.h"
50ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_options.h"
51ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_scheduler.h"
52ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_sigframe.h"      // For VG_(sigframe_destroy)()
53ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_signals.h"
54ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_syscall.h"
55ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_syswrap.h"
56ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_tooliface.h"
57ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "pub_core_stacks.h"        // VG_(register_stack)
58ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
59ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_types_n_macros.h"
60ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_syswrap-generic.h"    /* for decls of generic wrappers */
61ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_syswrap-linux.h"      /* for decls of linux-ish wrappers */
62ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_syswrap-linux-variants.h" /* decls of linux variant wrappers */
63ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#include "priv_syswrap-main.h"
64ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
65ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
66ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------------------------------------------------------------
67ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   clone() handling
68ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ------------------------------------------------------------------ */
69ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
70ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Call f(arg1), but first switch stacks, using 'stack' as the new
71ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stack, and use 'retaddr' as f's return-to address.  Also, clear all
72ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the integer registers before entering f.*/
73ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown__attribute__((noreturn))
74ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid ML_(call_on_new_stack_0_1) ( Addr stack,
75ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			          Addr retaddr,
76ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			          void (*f)(Word),
77ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  Word arg1 );
78ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  4(%esp) == stack
79ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//  8(%esp) == retaddr
80ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 12(%esp) == f
81ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// 16(%esp) == arg1
82ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownasm(
83ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown".text\n"
84ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown".globl vgModuleLocal_call_on_new_stack_0_1\n"
85ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"vgModuleLocal_call_on_new_stack_0_1:\n"
86ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"   movl %esp, %esi\n"     // remember old stack pointer
87ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"   movl 4(%esi), %esp\n"  // set stack
88ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"   pushl 16(%esi)\n"      // arg1 to stack
89ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"   pushl  8(%esi)\n"      // retaddr to stack
90ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"   pushl 12(%esi)\n"      // f to stack
91ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"   movl $0, %eax\n"       // zero all GP regs
92ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"   movl $0, %ebx\n"
93ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"   movl $0, %ecx\n"
94ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"   movl $0, %edx\n"
95ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"   movl $0, %esi\n"
96ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"   movl $0, %edi\n"
97ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"   movl $0, %ebp\n"
98ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"   ret\n"                 // jump to f
99ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"   ud2\n"                 // should never get here
100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown".previous\n"
101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown);
102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        Perform a clone system call.  clone is strange because it has
106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        fork()-like return-twice semantics, so it needs special
107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        handling here.
108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        Upon entry, we have:
110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            int (fn)(void*)     in  0+FSZ(%esp)
112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            void* child_stack   in  4+FSZ(%esp)
113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            int flags           in  8+FSZ(%esp)
114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            void* arg           in 12+FSZ(%esp)
115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pid_t* child_tid    in 16+FSZ(%esp)
116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pid_t* parent_tid   in 20+FSZ(%esp)
117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            void* tls_ptr       in 24+FSZ(%esp)
118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        System call requires:
120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            int    $__NR_clone  in %eax
122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            int    flags        in %ebx
123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            void*  child_stack  in %ecx
124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pid_t* parent_tid   in %edx
125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            pid_t* child_tid    in %edi
126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            void*  tls_ptr      in %esi
127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	Returns an Int encoded in the linux-x86 way, not a SysRes.
129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define FSZ               "4+4+4+4" /* frame size = retaddr+ebx+edi+esi */
131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define __NR_CLONE        VG_STRINGIFY(__NR_clone)
132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define __NR_EXIT         VG_STRINGIFY(__NR_exit)
133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownextern
135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownInt do_syscall_clone_x86_linux ( Word (*fn)(void *),
136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 void* stack,
137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 Int   flags,
138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 void* arg,
139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 Int*  child_tid,
140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 Int*  parent_tid,
141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                 vki_modify_ldt_t * );
142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownasm(
143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown".text\n"
144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"do_syscall_clone_x86_linux:\n"
145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        push    %ebx\n"
146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        push    %edi\n"
147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        push    %esi\n"
148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* set up child stack with function and arg */
150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        movl     4+"FSZ"(%esp), %ecx\n"    /* syscall arg2: child stack */
151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        movl    12+"FSZ"(%esp), %ebx\n"    /* fn arg */
152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        movl     0+"FSZ"(%esp), %eax\n"    /* fn */
153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        lea     -8(%ecx), %ecx\n"          /* make space on stack */
154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        movl    %ebx, 4(%ecx)\n"           /*   fn arg */
155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        movl    %eax, 0(%ecx)\n"           /*   fn */
156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* get other args to clone */
158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        movl     8+"FSZ"(%esp), %ebx\n"    /* syscall arg1: flags */
159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        movl    20+"FSZ"(%esp), %edx\n"    /* syscall arg3: parent tid * */
160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        movl    16+"FSZ"(%esp), %edi\n"    /* syscall arg5: child tid * */
161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        movl    24+"FSZ"(%esp), %esi\n"    /* syscall arg4: tls_ptr * */
162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        movl    $"__NR_CLONE", %eax\n"
163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        int     $0x80\n"                   /* clone() */
164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        testl   %eax, %eax\n"              /* child if retval == 0 */
165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        jnz     1f\n"
166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* CHILD - call thread function */
168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        popl    %eax\n"
169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        call    *%eax\n"                   /* call fn */
170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* exit with result */
172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        movl    %eax, %ebx\n"              /* arg1: return value from fn */
173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        movl    $"__NR_EXIT", %eax\n"
174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        int     $0x80\n"
175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         /* Hm, exit returned */
177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        ud2\n"
178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"1:\n"   /* PARENT or ERROR */
180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        pop     %esi\n"
181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        pop     %edi\n"
182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        pop     %ebx\n"
183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown"        ret\n"
184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown".previous\n"
185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown);
186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef FSZ
188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef __NR_CLONE
189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef __NR_EXIT
190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// forward declarations
193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void setup_child ( ThreadArchState*, ThreadArchState*, Bool );
194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic SysRes sys_set_thread_area ( ThreadId, vki_modify_ldt_t* );
195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   When a client clones, we need to keep track of the new thread.  This means:
198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   1. allocate a ThreadId+ThreadState+stack for the the thread
199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   2. initialize the thread's new VCPU state
201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   3. create the thread using the same args as the client requested,
203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   but using the scheduler entrypoint for EIP, and a separate stack
204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for ESP.
205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic SysRes do_clone ( ThreadId ptid,
207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         UInt flags, Addr esp,
208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         Int* parent_tidptr,
209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         Int* child_tidptr,
210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         vki_modify_ldt_t *tlsinfo)
211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   static const Bool debug = False;
213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ThreadId     ctid = VG_(alloc_ThreadState)();
215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ThreadState* ptst = VG_(get_ThreadState)(ptid);
216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ThreadState* ctst = VG_(get_ThreadState)(ctid);
217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UWord*       stack;
218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   NSegment const* seg;
219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes       res;
220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int          eax;
221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vki_sigset_t blockall, savedmask;
222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(sigfillset)(&blockall);
224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_(is_running_thread)(ptid));
226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_(is_valid_tid)(ctid));
227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   stack = (UWord*)ML_(allocstack)(ctid);
229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (stack == NULL) {
230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto out;
232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Copy register state
235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Both parent and child return to the same place, and the code
237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      following the clone syscall works out which is which, so we
238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      don't need to worry about it.
239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      The parent gets the child's new tid returned from clone, but the
241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      child gets 0.
242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      If the clone call specifies a NULL esp for the new thread, then
244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      it actually gets a copy of the parent's esp.
245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Note: the clone call done by the Quadrics Elan3 driver specifies
247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      clone flags of 0xF00, and it seems to rely on the assumption
248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      that the child inherits a copy of the parent's GDT.
249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      setup_child takes care of setting that up. */
250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   setup_child( &ctst->arch, &ptst->arch, True );
251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Make sys_clone appear to have returned Success(0) in the
253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      child. */
254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ctst->arch.vex.guest_EAX = 0;
255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (esp != 0)
257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctst->arch.vex.guest_ESP = esp;
258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ctst->os_state.parent = ptid;
260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* inherit signal mask */
262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ctst->sig_mask     = ptst->sig_mask;
263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ctst->tmp_sig_mask = ptst->sig_mask;
264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Start the child with its threadgroup being the same as the
266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      parent's.  This is so that any exit_group calls that happen
267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      after the child is created but before it sets its
268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      os_state.threadgroup field for real (in thread_wrapper in
269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      syswrap-linux.c), really kill the new thread.  a.k.a this avoids
270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      a race condition in which the thread is unkillable (via
271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      exit_group) because its threadgroup is not set.  The race window
272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      is probably only a few hundred or a few thousand cycles long.
273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      See #226116. */
274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ctst->os_state.threadgroup = ptst->os_state.threadgroup;
275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* We don't really know where the client stack is, because its
277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      allocated by the client.  The best we can do is look at the
278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      memory mappings and try to derive some useful information.  We
279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      assume that esp starts near its highest possible value, and can
280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      only go down to the start of the mmaped segment. */
281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   seg = VG_(am_find_nsegment)((Addr)esp);
282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (seg && seg->kind != SkResvn) {
283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctst->client_stack_highest_word = (Addr)VG_PGROUNDUP(esp);
284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctst->client_stack_szB = ctst->client_stack_highest_word - seg->start;
285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(register_stack)(seg->start, ctst->client_stack_highest_word);
287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (debug)
289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 VG_(printf)("tid %d: guessed client stack range %#lx-%#lx\n",
290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     ctid, seg->start, VG_PGROUNDUP(esp));
291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg,
293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   "!? New thread %d starts with ESP(%#lx) unmapped\n",
294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		   ctid, esp);
295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctst->client_stack_szB  = 0;
296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Assume the clone will succeed, and tell any tool that wants to
299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      know that this thread has come into existence.  We cannot defer
300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      it beyond this point because sys_set_thread_area, just below,
301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      causes tCheck to assert by making references to the new ThreadId
302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if we don't state the new thread exists prior to that point.
303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      If the clone fails, we'll send out a ll_exit notification for it
304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      at the out: label below, to clean up. */
305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_TRACK ( pre_thread_ll_create, ptid, ctid );
306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (flags & VKI_CLONE_SETTLS) {
308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (debug)
309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 VG_(printf)("clone child has SETTLS: tls info at %p: idx=%d "
310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     "base=%#lx limit=%x; esp=%#x fs=%x gs=%x\n",
311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     tlsinfo, tlsinfo->entry_number,
312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     tlsinfo->base_addr, tlsinfo->limit,
313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     ptst->arch.vex.guest_ESP,
314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     ctst->arch.vex.guest_FS, ctst->arch.vex.guest_GS);
315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      res = sys_set_thread_area(ctid, tlsinfo);
316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (sr_isError(res))
317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 goto out;
318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   flags &= ~VKI_CLONE_SETTLS;
321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* start the thread with everything blocked */
323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Create the new thread */
326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   eax = do_syscall_clone_x86_linux(
327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            ML_(start_thread_NORETURN), stack, flags, &VG_(threads)[ctid],
328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            child_tidptr, parent_tidptr, NULL
329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         );
330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res = VG_(mk_SysRes_x86_linux)( eax );
331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  out:
335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sr_isError(res)) {
336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* clone failed */
337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(cleanup_thread)(&ctst->arch);
338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ctst->status = VgTs_Empty;
339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* oops.  Better tell the tool the thread exited in a hurry :-) */
340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_TRACK( pre_thread_ll_exit, ctid );
341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------------------------------------------------------------
348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LDT/GDT simulation
349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ------------------------------------------------------------------ */
350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Details of the LDT simulation
352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   When a program runs natively, the linux kernel allows each *thread*
355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   in it to have its own LDT.  Almost all programs never do this --
356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   it's wildly unportable, after all -- and so the kernel never
357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   allocates the structure, which is just as well as an LDT occupies
358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   64k of memory (8192 entries of size 8 bytes).
359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   A thread may choose to modify its LDT entries, by doing the
361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   __NR_modify_ldt syscall.  In such a situation the kernel will then
362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   allocate an LDT structure for it.  Each LDT entry is basically a
363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (base, limit) pair.  A virtual address in a specific segment is
364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   translated to a linear address by adding the segment's base value.
365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   In addition, the virtual address must not exceed the limit value.
366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   To use an LDT entry, a thread loads one of the segment registers
368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   (%cs, %ss, %ds, %es, %fs, %gs) with the index of the LDT entry (0
369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   .. 8191) it wants to use.  In fact, the required value is (index <<
370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   3) + 7, but that's not important right now.  Any normal instruction
371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   which includes an addressing mode can then be made relative to that
372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LDT entry by prefixing the insn with a so-called segment-override
373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   prefix, a byte which indicates which of the 6 segment registers
374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   holds the LDT index.
375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Now, a key constraint is that valgrind's address checks operate in
377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   terms of linear addresses.  So we have to explicitly translate
378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   virtual addrs into linear addrs, and that means doing a complete
379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LDT simulation.
380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Calls to modify_ldt are intercepted.  For each thread, we maintain
382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   an LDT (with the same normally-never-allocated optimisation that
383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the kernel does).  This is updated as expected via calls to
384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   modify_ldt.
385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   When a thread does an amode calculation involving a segment
387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   override prefix, the relevant LDT entry for the thread is
388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   consulted.  It all works.
389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   There is a conceptual problem, which appears when switching back to
391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   native execution, either temporarily to pass syscalls to the
392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   kernel, or permanently, when debugging V.  Problem at such points
393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   is that it's pretty pointless to copy the simulated machine's
394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   segment registers to the real machine, because we'd also need to
395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   copy the simulated LDT into the real one, and that's prohibitively
396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   expensive.
397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Fortunately it looks like no syscalls rely on the segment regs or
399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LDT being correct, so we can get away with it.  Apart from that the
400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   simulation is pretty straightforward.  All 6 segment registers are
401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tracked, although only %ds, %es, %fs and %gs are allowed as
402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   prefixes.  Perhaps it could be restricted even more than that -- I
403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   am not sure what is and isn't allowed in user-mode.
404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown*/
405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Translate a struct modify_ldt_ldt_s to a VexGuestX86SegDescr, using
407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the Linux kernel's logic (cut-n-paste of code in
408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   linux/kernel/ldt.c).  */
409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid translate_to_hw_format ( /* IN  */ vki_modify_ldt_t* inn,
412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                              /* OUT */ VexGuestX86SegDescr* out,
413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                        Int oldmode )
414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt entry_1, entry_2;
416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(8 == sizeof(VexGuestX86SegDescr));
417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0)
419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("translate_to_hw_format: base %#lx, limit %d\n",
420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  inn->base_addr, inn->limit );
421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Allow LDTs to be cleared by the user. */
423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (inn->base_addr == 0 && inn->limit == 0) {
424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (oldmode ||
425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          (inn->contents == 0      &&
426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           inn->read_exec_only == 1   &&
427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           inn->seg_32bit == 0      &&
428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           inn->limit_in_pages == 0   &&
429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           inn->seg_not_present == 1   &&
430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           inn->useable == 0 )) {
431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         entry_1 = 0;
432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         entry_2 = 0;
433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto install;
434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   entry_1 = ((inn->base_addr & 0x0000ffff) << 16) |
438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             (inn->limit & 0x0ffff);
439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   entry_2 = (inn->base_addr & 0xff000000) |
440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             ((inn->base_addr & 0x00ff0000) >> 16) |
441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             (inn->limit & 0xf0000) |
442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             ((inn->read_exec_only ^ 1) << 9) |
443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             (inn->contents << 10) |
444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             ((inn->seg_not_present ^ 1) << 15) |
445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             (inn->seg_32bit << 22) |
446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             (inn->limit_in_pages << 23) |
447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             0x7000;
448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!oldmode)
449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      entry_2 |= (inn->useable << 20);
450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Install the new entry ...  */
452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  install:
453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out->LdtEnt.Words.word1 = entry_1;
454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   out->LdtEnt.Words.word2 = entry_2;
455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Create a zeroed-out GDT. */
458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VexGuestX86SegDescr* alloc_zeroed_x86_GDT ( void )
459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int nbytes = VEX_GUEST_X86_GDT_NENT * sizeof(VexGuestX86SegDescr);
461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return VG_(arena_calloc)(VG_AR_CORE, "di.syswrap-x86.azxG.1", nbytes, 1);
462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Create a zeroed-out LDT. */
465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic VexGuestX86SegDescr* alloc_zeroed_x86_LDT ( void )
466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int nbytes = VEX_GUEST_X86_LDT_NENT * sizeof(VexGuestX86SegDescr);
468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return VG_(arena_calloc)(VG_AR_CORE, "di.syswrap-x86.azxL.1", nbytes, 1);
469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Free up an LDT or GDT allocated by the above fns. */
472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void free_LDT_or_GDT ( VexGuestX86SegDescr* dt )
473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(dt);
475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(arena_free)(VG_AR_CORE, (void*)dt);
476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Copy contents between two existing LDTs. */
479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void copy_LDT_from_to ( VexGuestX86SegDescr* src,
480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               VexGuestX86SegDescr* dst )
481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(src);
484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(dst);
485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < VEX_GUEST_X86_LDT_NENT; i++)
486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dst[i] = src[i];
487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Copy contents between two existing GDTs. */
490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void copy_GDT_from_to ( VexGuestX86SegDescr* src,
491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               VexGuestX86SegDescr* dst )
492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int i;
494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(src);
495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(dst);
496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < VEX_GUEST_X86_GDT_NENT; i++)
497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      dst[i] = src[i];
498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Free this thread's DTs, if it has any. */
501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void deallocate_LGDTs_for_thread ( VexGuestX86State* vex )
502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(sizeof(HWord) == sizeof(void*));
504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0)
506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("deallocate_LGDTs_for_thread: "
507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "ldt = 0x%lx, gdt = 0x%lx\n",
508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  vex->guest_LDT, vex->guest_GDT );
509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex->guest_LDT != (HWord)NULL) {
511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      free_LDT_or_GDT( (VexGuestX86SegDescr*)vex->guest_LDT );
512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex->guest_LDT = (HWord)NULL;
513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (vex->guest_GDT != (HWord)NULL) {
516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      free_LDT_or_GDT( (VexGuestX86SegDescr*)vex->guest_GDT );
517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      vex->guest_GDT = (HWord)NULL;
518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * linux/kernel/ldt.c
524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown *
525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds
526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*
530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * read_ldt() is not really atomic - this is not a problem since
531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * synchronization of reads and writes done to the LDT has to be
532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * assured by user-space anyway. Writes are atomic, to protect
533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown * the security checks done on new descriptors.
534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown */
535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes read_ldt ( ThreadId tid, UChar* ptr, UInt bytecount )
537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes res;
539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt   i, size;
540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UChar* ldt;
541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0)
543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("read_ldt: tid = %d, ptr = %p, bytecount = %d\n",
544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  tid, ptr, bytecount );
545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*));
547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(8 == sizeof(VexGuestX86SegDescr));
548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ldt = (Char*)(VG_(threads)[tid].arch.vex.guest_LDT);
550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res = VG_(mk_SysRes_Success)( 0 );
551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ldt == NULL)
552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* LDT not allocated, meaning all entries are null */
553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto out;
554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   size = VEX_GUEST_X86_LDT_NENT * sizeof(VexGuestX86SegDescr);
556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (size > bytecount)
557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      size = bytecount;
558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res = VG_(mk_SysRes_Success)( size );
560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   for (i = 0; i < size; i++)
561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ptr[i] = ldt[i];
562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  out:
564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic
569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSysRes write_ldt ( ThreadId tid, void* ptr, UInt bytecount, Int oldmode )
570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes res;
572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VexGuestX86SegDescr* ldt;
573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vki_modify_ldt_t* ldt_info;
574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (0)
576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(printf)("write_ldt: tid = %d, ptr = %p, "
577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  "bytecount = %d, oldmode = %d\n",
578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  tid, ptr, bytecount, oldmode );
579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(8 == sizeof(VexGuestX86SegDescr));
581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*));
582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ldt      = (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_LDT;
584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ldt_info = (vki_modify_ldt_t*)ptr;
585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res = VG_(mk_SysRes_Error)( VKI_EINVAL );
587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (bytecount != sizeof(vki_modify_ldt_t))
588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto out;
589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res = VG_(mk_SysRes_Error)( VKI_EINVAL );
591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ldt_info->entry_number >= VEX_GUEST_X86_LDT_NENT)
592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto out;
593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ldt_info->contents == 3) {
594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (oldmode)
595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto out;
596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ldt_info->seg_not_present == 0)
597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         goto out;
598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If this thread doesn't have an LDT, we'd better allocate it
601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      now. */
602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ldt == NULL) {
603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ldt = alloc_zeroed_x86_LDT();
604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(threads)[tid].arch.vex.guest_LDT = (HWord)ldt;
605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Install the new entry ...  */
608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   translate_to_hw_format ( ldt_info, &ldt[ldt_info->entry_number], oldmode );
609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   res = VG_(mk_SysRes_Success)( 0 );
610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown  out:
612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return res;
613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic SysRes sys_modify_ldt ( ThreadId tid,
617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                               Int func, void* ptr, UInt bytecount )
618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes ret = VG_(mk_SysRes_Error)( VKI_ENOSYS );
620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (func) {
622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0:
623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ret = read_ldt(tid, ptr, bytecount);
624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 1:
626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ret = write_ldt(tid, ptr, bytecount, 1);
627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 2:
629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(unimplemented)("sys_modify_ldt: func == 2");
630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* god knows what this is about */
631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* ret = read_default_ldt(ptr, bytecount); */
632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*UNREACHED*/
633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0x11:
635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ret = write_ldt(tid, ptr, bytecount, 0);
636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return ret;
639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic SysRes sys_set_thread_area ( ThreadId tid, vki_modify_ldt_t* info )
643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int                  idx;
645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VexGuestX86SegDescr* gdt;
646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(8 == sizeof(VexGuestX86SegDescr));
648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*));
649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (info == NULL)
651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return VG_(mk_SysRes_Error)( VKI_EFAULT );
652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   gdt = (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_GDT;
654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If the thread doesn't have a GDT, allocate it now. */
656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!gdt) {
657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      gdt = alloc_zeroed_x86_GDT();
658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(threads)[tid].arch.vex.guest_GDT = (HWord)gdt;
659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   idx = info->entry_number;
662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (idx == -1) {
664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Find and use the first free entry.  Don't allocate entry
665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         zero, because the hardware will never do that, and apparently
666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         doing so confuses some code (perhaps stuff running on
667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         Wine). */
668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      for (idx = 1; idx < VEX_GUEST_X86_GDT_NENT; idx++) {
669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         if (gdt[idx].LdtEnt.Words.word1 == 0
670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             && gdt[idx].LdtEnt.Words.word2 == 0)
671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown            break;
672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (idx == VEX_GUEST_X86_GDT_NENT)
675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return VG_(mk_SysRes_Error)( VKI_ESRCH );
676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else if (idx < 0 || idx == 0 || idx >= VEX_GUEST_X86_GDT_NENT) {
677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Similarly, reject attempts to use GDT[0]. */
678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return VG_(mk_SysRes_Error)( VKI_EINVAL );
679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   translate_to_hw_format(info, &gdt[idx], 0);
682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_TRACK( pre_mem_write, Vg_CoreSysCall, tid,
684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             "set_thread_area(info->entry)",
685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             (Addr) & info->entry_number, sizeof(unsigned int) );
686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   info->entry_number = idx;
687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_TRACK( post_mem_write, Vg_CoreSysCall, tid,
688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             (Addr) & info->entry_number, sizeof(unsigned int) );
689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return VG_(mk_SysRes_Success)( 0 );
691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic SysRes sys_get_thread_area ( ThreadId tid, vki_modify_ldt_t* info )
695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int idx;
697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VexGuestX86SegDescr* gdt;
698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*));
700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(8 == sizeof(VexGuestX86SegDescr));
701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (info == NULL)
703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return VG_(mk_SysRes_Error)( VKI_EFAULT );
704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   idx = info->entry_number;
706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (idx < 0 || idx >= VEX_GUEST_X86_GDT_NENT)
708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return VG_(mk_SysRes_Error)( VKI_EINVAL );
709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   gdt = (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_GDT;
711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* If the thread doesn't have a GDT, allocate it now. */
713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!gdt) {
714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      gdt = alloc_zeroed_x86_GDT();
715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(threads)[tid].arch.vex.guest_GDT = (HWord)gdt;
716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   info->base_addr = ( gdt[idx].LdtEnt.Bits.BaseHi << 24 ) |
719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     ( gdt[idx].LdtEnt.Bits.BaseMid << 16 ) |
720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     gdt[idx].LdtEnt.Bits.BaseLow;
721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   info->limit = ( gdt[idx].LdtEnt.Bits.LimitHi << 16 ) |
722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                   gdt[idx].LdtEnt.Bits.LimitLow;
723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   info->seg_32bit = gdt[idx].LdtEnt.Bits.Default_Big;
724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   info->contents = ( gdt[idx].LdtEnt.Bits.Type >> 2 ) & 0x3;
725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   info->read_exec_only = ( gdt[idx].LdtEnt.Bits.Type & 0x1 ) ^ 0x1;
726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   info->limit_in_pages = gdt[idx].LdtEnt.Bits.Granularity;
727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   info->seg_not_present = gdt[idx].LdtEnt.Bits.Pres ^ 0x1;
728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   info->useable = gdt[idx].LdtEnt.Bits.Sys;
729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   info->reserved = 0;
730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return VG_(mk_SysRes_Success)( 0 );
732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------------------------------------------------------------
735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   More thread stuff
736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ------------------------------------------------------------------ */
737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownvoid VG_(cleanup_thread) ( ThreadArchState* arch )
739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Release arch-specific resources held by this thread. */
741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* On x86, we have to dump the LDT and GDT. */
742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   deallocate_LGDTs_for_thread( &arch->vex );
743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic void setup_child ( /*OUT*/ ThreadArchState *child,
747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          /*IN*/  ThreadArchState *parent,
748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                          Bool inherit_parents_GDT )
749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* We inherit our parent's guest state. */
751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   child->vex = parent->vex;
752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   child->vex_shadow1 = parent->vex_shadow1;
753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   child->vex_shadow2 = parent->vex_shadow2;
754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* We inherit our parent's LDT. */
756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (parent->vex.guest_LDT == (HWord)NULL) {
757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* We hope this is the common case. */
758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      child->vex.guest_LDT = (HWord)NULL;
759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   } else {
760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* No luck .. we have to take a copy of the parent's. */
761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      child->vex.guest_LDT = (HWord)alloc_zeroed_x86_LDT();
762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      copy_LDT_from_to( (VexGuestX86SegDescr*)parent->vex.guest_LDT,
763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (VexGuestX86SegDescr*)child->vex.guest_LDT );
764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Either we start with an empty GDT (the usual case) or inherit a
767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      copy of our parents' one (Quadrics Elan3 driver -style clone
768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      only). */
769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   child->vex.guest_GDT = (HWord)NULL;
770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (inherit_parents_GDT && parent->vex.guest_GDT != (HWord)NULL) {
772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      child->vex.guest_GDT = (HWord)alloc_zeroed_x86_GDT();
773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      copy_GDT_from_to( (VexGuestX86SegDescr*)parent->vex.guest_GDT,
774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        (VexGuestX86SegDescr*)child->vex.guest_GDT );
775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------------------------------------------------------------
780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE/POST wrappers for x86/Linux-specific syscalls
781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ------------------------------------------------------------------ */
782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PRE(name)       DEFN_PRE_TEMPLATE(x86_linux, name)
784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define POST(name)      DEFN_POST_TEMPLATE(x86_linux, name)
785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Add prototypes for the wrappers declared here, so that gcc doesn't
787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   harass us for not having prototypes.  Really this is a kludge --
788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   the right thing to do is to make these wrappers 'static' since they
789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   aren't visible outside this file, but that requires even more macro
790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   magic. */
791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDECL_TEMPLATE(x86_linux, sys_socketcall);
792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDECL_TEMPLATE(x86_linux, sys_stat64);
793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDECL_TEMPLATE(x86_linux, sys_fstatat64);
794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDECL_TEMPLATE(x86_linux, sys_fstat64);
795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDECL_TEMPLATE(x86_linux, sys_lstat64);
796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDECL_TEMPLATE(x86_linux, sys_clone);
797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDECL_TEMPLATE(x86_linux, old_mmap);
798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDECL_TEMPLATE(x86_linux, sys_mmap2);
799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDECL_TEMPLATE(x86_linux, sys_sigreturn);
800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDECL_TEMPLATE(x86_linux, sys_ipc);
801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDECL_TEMPLATE(x86_linux, sys_rt_sigreturn);
802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDECL_TEMPLATE(x86_linux, sys_modify_ldt);
803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDECL_TEMPLATE(x86_linux, sys_set_thread_area);
804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDECL_TEMPLATE(x86_linux, sys_get_thread_area);
805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDECL_TEMPLATE(x86_linux, sys_ptrace);
806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDECL_TEMPLATE(x86_linux, old_select);
807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDECL_TEMPLATE(x86_linux, sys_vm86old);
808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDECL_TEMPLATE(x86_linux, sys_vm86);
809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownDECL_TEMPLATE(x86_linux, sys_syscall223);
810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(old_select)
812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* struct sel_arg_struct {
814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      unsigned long n;
815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      fd_set *inp, *outp, *exp;
816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      struct timeval *tvp;
817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      };
818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(long, "old_select", struct sel_arg_struct *, args);
820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_READ( "old_select(args)", ARG1, 5*sizeof(UWord) );
821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt* arg_struct = (UInt*)ARG1;
824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UInt a1, a2, a3, a4, a5;
825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      a1 = arg_struct[0];
827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      a2 = arg_struct[1];
828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      a3 = arg_struct[2];
829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      a4 = arg_struct[3];
830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      a5 = arg_struct[4];
831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRINT("old_select ( %d, %#x, %#x, %#x, %#x )", a1,a2,a3,a4,a5);
833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (a2 != (Addr)NULL)
834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PRE_MEM_READ( "old_select(readfds)",   a2, a1/8 /* __FD_SETSIZE/8 */ );
835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (a3 != (Addr)NULL)
836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PRE_MEM_READ( "old_select(writefds)",  a3, a1/8 /* __FD_SETSIZE/8 */ );
837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (a4 != (Addr)NULL)
838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PRE_MEM_READ( "old_select(exceptfds)", a4, a1/8 /* __FD_SETSIZE/8 */ );
839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (a5 != (Addr)NULL)
840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PRE_MEM_READ( "old_select(timeout)", a5, sizeof(struct vki_timeval) );
841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_clone)
845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UInt cloneflags;
847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Bool badarg = False;
848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_clone ( %lx, %#lx, %#lx, %#lx, %#lx )",ARG1,ARG2,ARG3,ARG4,ARG5);
850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(int, "clone",
851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned long, flags,
852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 void *, child_stack);
853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG1 & VKI_CLONE_PARENT_SETTID) {
855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(tdict).track_pre_reg_read) {
856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PRA3("clone", int *, parent_tidptr);
857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int),
860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             VKI_PROT_WRITE)) {
861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         badarg = True;
862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG1 & VKI_CLONE_SETTLS) {
865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(tdict).track_pre_reg_read) {
866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PRA4("clone", vki_modify_ldt_t *, tlsinfo);
867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ("clone(tlsinfo)", ARG4, sizeof(vki_modify_ldt_t));
869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!VG_(am_is_valid_for_client)(ARG4, sizeof(vki_modify_ldt_t),
870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             VKI_PROT_READ)) {
871ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         badarg = True;
872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (VG_(tdict).track_pre_reg_read) {
876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         PRA5("clone", int *, child_tidptr);
877ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE("clone(child_tidptr)", ARG5, sizeof(Int));
879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!VG_(am_is_valid_for_client)(ARG5, sizeof(Int),
880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                             VKI_PROT_WRITE)) {
881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         badarg = True;
882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      }
883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (badarg) {
886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SET_STATUS_Failure( VKI_EFAULT );
887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   cloneflags = ARG1;
891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!ML_(client_signal_OK)(ARG1 & VKI_CSIGNAL)) {
893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SET_STATUS_Failure( VKI_EINVAL );
894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Be ultra-paranoid and filter out any clone-variants we don't understand:
898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      - ??? specifies clone flags of 0x100011
899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      - ??? specifies clone flags of 0x1200011.
900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      - NPTL specifies clone flags of 0x7D0F00.
901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      - The Quadrics Elan3 driver specifies clone flags of 0xF00.
902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      - Newer Quadrics Elan3 drivers with NTPL support specify 0x410F00.
903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Everything else is rejected.
904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   */
905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (
906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        1 ||
907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown        /* 11 Nov 05: for the time being, disable this ultra-paranoia.
908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown           The switch below probably does a good enough job. */
909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          (cloneflags == 0x100011 || cloneflags == 0x1200011
910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  || cloneflags == 0x7D0F00
911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  || cloneflags == 0x790F00
912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  || cloneflags == 0x3D0F00
913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  || cloneflags == 0x410F00
914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  || cloneflags == 0xF00
915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                  || cloneflags == 0xF21)) {
916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     /* OK */
917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   else {
919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Nah.  We don't like it.  Go away. */
920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      goto reject;
921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Only look at the flags we really care about */
924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS
925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                         | VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* thread creation */
928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SET_STATUS_from_SysRes(
929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         do_clone(tid,
930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  ARG1,         /* flags */
931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (Addr)ARG2,   /* child ESP */
932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (Int *)ARG3,  /* parent_tidptr */
933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (Int *)ARG5,  /* child_tidptr */
934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  (vki_modify_ldt_t *)ARG4)); /* set_tls */
935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* FALLTHROUGH - assume vfork == fork */
939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case 0: /* plain fork */
942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SET_STATUS_from_SysRes(
943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ML_(do_fork_clone)(tid,
944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       cloneflags,      /* flags */
945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (Int *)ARG3,     /* parent_tidptr */
946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                       (Int *)ARG5));   /* child_tidptr */
947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   reject:
951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* should we just ENOSYS? */
952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg, "\n");
953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%lx\n", ARG1);
954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg, "\n");
955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg, "The only supported clone() uses are:\n");
956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg, " - via a threads library (LinuxThreads or NPTL)\n");
957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg, " - via the implementation of fork or vfork\n");
958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_UserMsg, " - for the Quadrics Elan3 user-space driver\n");
959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(unimplemented)
960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ("Valgrind does not support general clone().");
961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (SUCCESS) {
964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ARG1 & VKI_CLONE_PARENT_SETTID)
965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         POST_MEM_WRITE(ARG3, sizeof(Int));
966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID))
967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         POST_MEM_WRITE(ARG5, sizeof(Int));
968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* Thread creation was successful; let the child have the chance
970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         to run */
971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *flags |= SfYieldAfter;
972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_sigreturn)
976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for
978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      an explanation of what follows. */
979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ThreadState* tst;
981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_sigreturn ( )");
982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_(is_valid_tid)(tid));
984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(tid >= 1 && tid < VG_N_THREADS);
985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_(is_running_thread)(tid));
986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Adjust esp to point to start of frame; skip back up over
988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      sigreturn sequence's "popl %eax" and handler ret addr */
989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tst = VG_(get_ThreadState)(tid);
990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tst->arch.vex.guest_ESP -= sizeof(Addr)+sizeof(Word);
991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* XXX why does ESP change differ from rt_sigreturn case below? */
992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* This is only so that the EIP is (might be) useful to report if
994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      something goes wrong in the sigreturn */
995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ML_(fixup_guest_state_to_restart_syscall)(&tst->arch);
996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Restore register state from frame and remove it */
998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(sigframe_destroy)(tid, False);
999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Tell the driver not to update the guest state with the "result",
1001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      and set a bogus result to keep it happy. */
1002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfNoWriteResult;
1003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SET_STATUS_Success(0);
1004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Check to see if any signals arose as a result of this. */
1006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfPollAfter;
1007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_rt_sigreturn)
1010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* See comments on PRE(sys_rt_sigreturn) in syswrap-amd64-linux.c for
1012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      an explanation of what follows. */
1013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ThreadState* tst;
1015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_rt_sigreturn ( )");
1016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_(is_valid_tid)(tid));
1018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(tid >= 1 && tid < VG_N_THREADS);
1019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VG_(is_running_thread)(tid));
1020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Adjust esp to point to start of frame; skip back up over handler
1022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ret addr */
1023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tst = VG_(get_ThreadState)(tid);
1024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   tst->arch.vex.guest_ESP -= sizeof(Addr);
1025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* XXX why does ESP change differ from sigreturn case above? */
1026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* This is only so that the EIP is (might be) useful to report if
1028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      something goes wrong in the sigreturn */
1029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ML_(fixup_guest_state_to_restart_syscall)(&tst->arch);
1030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Restore register state from frame and remove it */
1032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   VG_(sigframe_destroy)(tid, True);
1033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Tell the driver not to update the guest state with the "result",
1035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      and set a bogus result to keep it happy. */
1036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfNoWriteResult;
1037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SET_STATUS_Success(0);
1038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Check to see if any signals arose as a result of this. */
1040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfPollAfter;
1041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_modify_ldt)
1044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_modify_ldt ( %ld, %#lx, %ld )", ARG1,ARG2,ARG3);
1046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ3(int, "modify_ldt", int, func, void *, ptr,
1047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned long, bytecount);
1048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG1 == 0) {
1050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* read the LDT into ptr */
1051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "modify_ldt(ptr)", ARG2, ARG3 );
1052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG1 == 1 || ARG1 == 0x11) {
1054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* write the LDT with the entry pointed at by ptr */
1055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "modify_ldt(ptr)", ARG2, sizeof(vki_modify_ldt_t) );
1056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* "do" the syscall ourselves; the kernel never sees it */
1058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SET_STATUS_from_SysRes( sys_modify_ldt( tid, ARG1, (void*)ARG2, ARG3 ) );
1059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG1 == 0 && SUCCESS && RES > 0) {
1061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( ARG2, RES );
1062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_set_thread_area)
1066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_set_thread_area ( %#lx )", ARG1);
1068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(int, "set_thread_area", struct user_desc *, u_info)
1069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_READ( "set_thread_area(u_info)", ARG1, sizeof(vki_modify_ldt_t) );
1070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* "do" the syscall ourselves; the kernel never sees it */
1072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SET_STATUS_from_SysRes( sys_set_thread_area( tid, (void *)ARG1 ) );
1073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_get_thread_area)
1076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_get_thread_area ( %#lx )", ARG1);
1078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(int, "get_thread_area", struct user_desc *, u_info)
1079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_WRITE( "get_thread_area(u_info)", ARG1, sizeof(vki_modify_ldt_t) );
1080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* "do" the syscall ourselves; the kernel never sees it */
1082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SET_STATUS_from_SysRes( sys_get_thread_area( tid, (void *)ARG1 ) );
1083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (SUCCESS) {
1085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( ARG1, sizeof(vki_modify_ldt_t) );
1086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// Parts of this are x86-specific, but the *PEEK* cases are generic.
1090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
1091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// ARG3 is only used for pointers into the traced process's address
1092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// space and for offsets into the traced process's struct
1093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// user_regs_struct. It is never a pointer into this process's memory
1094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// space, and we should therefore not check anything it points to.
1095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_ptrace)
1096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_ptrace ( %ld, %ld, %#lx, %#lx )", ARG1,ARG2,ARG3,ARG4);
1098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ4(int, "ptrace",
1099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 long, request, long, pid, long, addr, long, data);
1100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ARG1) {
1101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_PTRACE_PEEKTEXT:
1102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_PTRACE_PEEKDATA:
1103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_PTRACE_PEEKUSR:
1104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "ptrace(peek)", ARG4,
1105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     sizeof (long));
1106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_PTRACE_GETREGS:
1108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "ptrace(getregs)", ARG4,
1109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     sizeof (struct vki_user_regs_struct));
1110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_PTRACE_GETFPREGS:
1112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "ptrace(getfpregs)", ARG4,
1113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     sizeof (struct vki_user_i387_struct));
1114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_PTRACE_GETFPXREGS:
1116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "ptrace(getfpxregs)", ARG4,
1117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     sizeof(struct vki_user_fxsr_struct) );
1118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_PTRACE_SETREGS:
1120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "ptrace(setregs)", ARG4,
1121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     sizeof (struct vki_user_regs_struct));
1122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_PTRACE_SETFPREGS:
1124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "ptrace(setfpregs)", ARG4,
1125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		     sizeof (struct vki_user_i387_struct));
1126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_PTRACE_SETFPXREGS:
1128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "ptrace(setfpxregs)", ARG4,
1129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     sizeof(struct vki_user_fxsr_struct) );
1130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_PTRACE_GETEVENTMSG:
1132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "ptrace(geteventmsg)", ARG4, sizeof(unsigned long));
1133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_PTRACE_GETSIGINFO:
1135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "ptrace(getsiginfo)", ARG4, sizeof(vki_siginfo_t));
1136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_PTRACE_SETSIGINFO:
1138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "ptrace(setsiginfo)", ARG4, sizeof(vki_siginfo_t));
1139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
1141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_ptrace)
1146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ARG1) {
1148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_PTRACE_PEEKTEXT:
1149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_PTRACE_PEEKDATA:
1150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_PTRACE_PEEKUSR:
1151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( ARG4, sizeof (long));
1152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_PTRACE_GETREGS:
1154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( ARG4, sizeof (struct vki_user_regs_struct));
1155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_PTRACE_GETFPREGS:
1157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( ARG4, sizeof (struct vki_user_i387_struct));
1158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_PTRACE_GETFPXREGS:
1160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( ARG4, sizeof(struct vki_user_fxsr_struct) );
1161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_PTRACE_GETEVENTMSG:
1163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( ARG4, sizeof(unsigned long));
1164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_PTRACE_GETSIGINFO:
1166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* XXX: This is a simplification. Different parts of the
1167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * siginfo_t are valid depending on the type of signal.
1168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       */
1169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( ARG4, sizeof(vki_siginfo_t));
1170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
1172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic Addr deref_Addr ( ThreadId tid, Addr a, Char* s )
1177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Addr* a_p = (Addr*)a;
1179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_READ( s, (Addr)a_p, sizeof(Addr) );
1180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return *a_p;
1181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_ipc)
1184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_ipc ( %ld, %ld, %ld, %ld, %#lx, %ld )", ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
1186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // XXX: this is simplistic -- some args are not used in all circumstances.
1187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ6(int, "ipc",
1188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 vki_uint, call, int, first, int, second, int, third,
1189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 void *, ptr, long, fifth)
1190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ARG1 /* call */) {
1192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SEMOP:
1193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(generic_PRE_sys_semop)( tid, ARG2, ARG5, ARG3 );
1194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *flags |= SfMayBlock;
1195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SEMGET:
1197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SEMCTL:
1199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UWord arg = deref_Addr( tid, ARG5, "semctl(arg)" );
1201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(generic_PRE_sys_semctl)( tid, ARG2, ARG3, ARG4, arg );
1202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SEMTIMEDOP:
1205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(generic_PRE_sys_semtimedop)( tid, ARG2, ARG5, ARG3, ARG6 );
1206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      *flags |= SfMayBlock;
1207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_MSGSND:
1209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(linux_PRE_sys_msgsnd)( tid, ARG2, ARG5, ARG3, ARG4 );
1210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((ARG4 & VKI_IPC_NOWAIT) == 0)
1211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *flags |= SfMayBlock;
1212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_MSGRCV:
1214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr msgp;
1216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Word msgtyp;
1217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      msgp = deref_Addr( tid,
1219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			 (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgp),
1220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			 "msgrcv(msgp)" );
1221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      msgtyp = deref_Addr( tid,
1222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			   (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgtyp),
1223ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			   "msgrcv(msgp)" );
1224ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1225ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(linux_PRE_sys_msgrcv)( tid, ARG2, msgp, ARG3, msgtyp, ARG4 );
1226ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1227ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if ((ARG4 & VKI_IPC_NOWAIT) == 0)
1228ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         *flags |= SfMayBlock;
1229ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1230ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1231ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_MSGGET:
1232ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1233ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_MSGCTL:
1234ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(linux_PRE_sys_msgctl)( tid, ARG2, ARG3, ARG5 );
1235ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1236ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SHMAT:
1237ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1238ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UWord w;
1239ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "shmat(raddr)", ARG4, sizeof(Addr) );
1240ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      w = ML_(generic_PRE_sys_shmat)( tid, ARG2, ARG5, ARG3 );
1241ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (w == 0)
1242ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         SET_STATUS_Failure( VKI_EINVAL );
1243ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
1244ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ARG5 = w;
1245ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1246ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1247ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SHMDT:
1248ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (!ML_(generic_PRE_sys_shmdt)(tid, ARG5))
1249ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown	 SET_STATUS_Failure( VKI_EINVAL );
1250ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1251ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SHMGET:
1252ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1253ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SHMCTL: /* IPCOP_shmctl */
1254ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(generic_PRE_sys_shmctl)( tid, ARG2, ARG3, ARG5 );
1255ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1256ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
1257ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg, "FATAL: unhandled syscall(ipc) %ld\n", ARG1 );
1258ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(core_panic)("... bye!\n");
1259ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break; /*NOTREACHED*/
1260ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1261ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1262ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1263ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_ipc)
1264ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1265ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(SUCCESS);
1266ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ARG1 /* call */) {
1267ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SEMOP:
1268ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SEMGET:
1269ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1270ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SEMCTL:
1271ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1272ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      UWord arg = deref_Addr( tid, ARG5, "semctl(arg)" );
1273ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(generic_PRE_sys_semctl)( tid, ARG2, ARG3, ARG4, arg );
1274ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1275ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1276ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SEMTIMEDOP:
1277ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_MSGSND:
1278ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1279ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_MSGRCV:
1280ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1281ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr msgp;
1282ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Word msgtyp;
1283ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1284ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      msgp = deref_Addr( tid,
1285ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			 (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgp),
1286ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			 "msgrcv(msgp)" );
1287ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      msgtyp = deref_Addr( tid,
1288ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			   (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgtyp),
1289ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			   "msgrcv(msgp)" );
1290ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1291ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(linux_POST_sys_msgrcv)( tid, RES, ARG2, msgp, ARG3, msgtyp, ARG4 );
1292ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1293ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1294ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_MSGGET:
1295ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1296ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_MSGCTL:
1297ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(linux_POST_sys_msgctl)( tid, RES, ARG2, ARG3, ARG5 );
1298ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1299ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SHMAT:
1300ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   {
1301ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      Addr addr;
1302ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1303ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* force readability. before the syscall it is
1304ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * indeed uninitialized, as can be seen in
1305ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * glibc/sysdeps/unix/sysv/linux/shmat.c */
1306ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( ARG4, sizeof( Addr ) );
1307ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1308ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      addr = deref_Addr ( tid, ARG4, "shmat(addr)" );
1309ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(generic_POST_sys_shmat)( tid, addr, ARG2, ARG5, ARG3 );
1310ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1311ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1312ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SHMDT:
1313ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(generic_POST_sys_shmdt)( tid, RES, ARG5 );
1314ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1315ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SHMGET:
1316ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1317ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SHMCTL:
1318ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(generic_POST_sys_shmctl)( tid, RES, ARG2, ARG3, ARG5 );
1319ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1320ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
1321ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg,
1322ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		   "FATAL: unhandled syscall(ipc) %ld\n",
1323ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown		   ARG1 );
1324ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(core_panic)("... bye!\n");
1325ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break; /*NOTREACHED*/
1326ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1327ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1328ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1329ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(old_mmap)
1330ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1331ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* struct mmap_arg_struct {
1332ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unsigned long addr;
1333ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unsigned long len;
1334ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unsigned long prot;
1335ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unsigned long flags;
1336ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unsigned long fd;
1337ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         unsigned long offset;
1338ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }; */
1339ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UWord a1, a2, a3, a4, a5, a6;
1340ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes r;
1341ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1342ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   UWord* args = (UWord*)ARG1;
1343ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(long, "old_mmap", struct mmap_arg_struct *, args);
1344ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_READ( "old_mmap(args)", (Addr)args, 6*sizeof(UWord) );
1345ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1346ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a1 = args[1-1];
1347ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a2 = args[2-1];
1348ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a3 = args[3-1];
1349ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a4 = args[4-1];
1350ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a5 = args[5-1];
1351ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   a6 = args[6-1];
1352ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1353ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("old_mmap ( %#lx, %llu, %ld, %ld, %ld, %ld )",
1354ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         a1, (ULong)a2, a3, a4, a5, a6 );
1355ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1356ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r = ML_(generic_PRE_sys_mmap)( tid, a1, a2, a3, a4, a5, (Off64T)a6 );
1357ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SET_STATUS_from_SysRes(r);
1358ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1359ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1360ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_mmap2)
1361ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1362ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes r;
1363ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1364ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Exactly like old_mmap() except:
1365ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //  - all 6 args are passed in regs, rather than in a memory-block.
1366ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //  - the file offset is specified in pagesize units rather than bytes,
1367ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   //    so that it can be used for files bigger than 2^32 bytes.
1368ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // pagesize or 4K-size units in offset?  For ppc32/64-linux, this is
1369ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // 4K-sized.  Assert that the page size is 4K here for safety.
1370ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(VKI_PAGE_SIZE == 4096);
1371ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_mmap2 ( %#lx, %llu, %ld, %ld, %ld, %ld )",
1372ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         ARG1, (ULong)ARG2, ARG3, ARG4, ARG5, ARG6 );
1373ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ6(long, "mmap2",
1374ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned long, start, unsigned long, length,
1375ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned long, prot,  unsigned long, flags,
1376ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 unsigned long, fd,    unsigned long, offset);
1377ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1378ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5,
1379ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       4096 * (Off64T)ARG6 );
1380ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SET_STATUS_from_SysRes(r);
1381ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1382ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1383ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// XXX: lstat64/fstat64/stat64 are generic, but not necessarily
1384ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// applicable to every architecture -- I think only to 32-bit archs.
1385ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// We're going to need something like linux/core_os32.h for such
1386ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// things, eventually, I think.  --njn
1387ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_lstat64)
1388ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1389ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_lstat64 ( %#lx(%s), %#lx )",ARG1,(char*)ARG1,ARG2);
1390ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "lstat64", char *, file_name, struct stat64 *, buf);
1391ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "lstat64(file_name)", ARG1 );
1392ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_WRITE( "lstat64(buf)", ARG2, sizeof(struct vki_stat64) );
1393ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1394ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1395ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_lstat64)
1396ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1397ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(SUCCESS);
1398ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (RES == 0) {
1399ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
1400ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1401ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1402ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1403ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_stat64)
1404ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1405ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_stat64 ( %#lx(%s), %#lx )",ARG1,(char*)ARG1,ARG2);
1406ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "stat64", char *, file_name, struct stat64 *, buf);
1407ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "stat64(file_name)", ARG1 );
1408ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_WRITE( "stat64(buf)", ARG2, sizeof(struct vki_stat64) );
1409ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1410ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1411ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_stat64)
1412ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1413ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
1414ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1415ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1416ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_fstatat64)
1417ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1418ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_fstatat64 ( %ld, %#lx(%s), %#lx )",ARG1,ARG2,(char*)ARG2,ARG3);
1419ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ3(long, "fstatat64",
1420ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                 int, dfd, char *, file_name, struct stat64 *, buf);
1421ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_RASCIIZ( "fstatat64(file_name)", ARG2 );
1422ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_WRITE( "fstatat64(buf)", ARG3, sizeof(struct vki_stat64) );
1423ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1424ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1425ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_fstatat64)
1426ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1427ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   POST_MEM_WRITE( ARG3, sizeof(struct vki_stat64) );
1428ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1429ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1430ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_fstat64)
1431ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1432ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_fstat64 ( %ld, %#lx )",ARG1,ARG2);
1433ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "fstat64", unsigned long, fd, struct stat64 *, buf);
1434ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_WRITE( "fstat64(buf)", ARG2, sizeof(struct vki_stat64) );
1435ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1436ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1437ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_fstat64)
1438ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1439ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
1440ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1441ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1442ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_socketcall)
1443ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1444ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define ARG2_0  (((UWord*)ARG2)[0])
1445ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define ARG2_1  (((UWord*)ARG2)[1])
1446ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define ARG2_2  (((UWord*)ARG2)[2])
1447ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define ARG2_3  (((UWord*)ARG2)[3])
1448ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define ARG2_4  (((UWord*)ARG2)[4])
1449ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define ARG2_5  (((UWord*)ARG2)[5])
1450ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1451ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock;
1452ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_socketcall ( %ld, %#lx )",ARG1,ARG2);
1453ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(long, "socketcall", int, call, unsigned long *, args);
1454ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1455ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ARG1 /* request */) {
1456ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1457ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_SOCKETPAIR:
1458ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* int socketpair(int d, int type, int protocol, int sv[2]); */
1459ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "socketcall.socketpair(args)", ARG2, 4*sizeof(Addr) );
1460ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(generic_PRE_sys_socketpair)( tid, ARG2_0, ARG2_1, ARG2_2, ARG2_3 );
1461ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1462ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1463ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_SOCKET:
1464ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* int socket(int domain, int type, int protocol); */
1465ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "socketcall.socket(args)", ARG2, 3*sizeof(Addr) );
1466ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1467ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1468ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_BIND:
1469ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* int bind(int sockfd, struct sockaddr *my_addr,
1470ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                  int addrlen); */
1471ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "socketcall.bind(args)", ARG2, 3*sizeof(Addr) );
1472ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(generic_PRE_sys_bind)( tid, ARG2_0, ARG2_1, ARG2_2 );
1473ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1474ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1475ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_LISTEN:
1476ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* int listen(int s, int backlog); */
1477ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "socketcall.listen(args)", ARG2, 2*sizeof(Addr) );
1478ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1479ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1480ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_ACCEPT: {
1481ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* int accept(int s, struct sockaddr *addr, int *addrlen); */
1482ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "socketcall.accept(args)", ARG2, 3*sizeof(Addr) );
1483ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(generic_PRE_sys_accept)( tid, ARG2_0, ARG2_1, ARG2_2 );
1484ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1485ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1486ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1487ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_ACCEPT4: {
1488ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /*int accept(int s, struct sockaddr *add, int *addrlen, int flags)*/
1489ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "socketcall.accept4(args)", ARG2, 4*sizeof(Addr) );
1490ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(generic_PRE_sys_accept)( tid, ARG2_0, ARG2_1, ARG2_2 );
1491ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1492ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1493ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1494ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_SENDTO:
1495ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* int sendto(int s, const void *msg, int len,
1496ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    unsigned int flags,
1497ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                    const struct sockaddr *to, int tolen); */
1498ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "socketcall.sendto(args)", ARG2, 6*sizeof(Addr) );
1499ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(generic_PRE_sys_sendto)( tid, ARG2_0, ARG2_1, ARG2_2,
1500ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                   ARG2_3, ARG2_4, ARG2_5 );
1501ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1502ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1503ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_SEND:
1504ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* int send(int s, const void *msg, size_t len, int flags); */
1505ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "socketcall.send(args)", ARG2, 4*sizeof(Addr) );
1506ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(generic_PRE_sys_send)( tid, ARG2_0, ARG2_1, ARG2_2 );
1507ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1508ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1509ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_RECVFROM:
1510ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* int recvfrom(int s, void *buf, int len, unsigned int flags,
1511ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         struct sockaddr *from, int *fromlen); */
1512ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "socketcall.recvfrom(args)", ARG2, 6*sizeof(Addr) );
1513ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(generic_PRE_sys_recvfrom)( tid, ARG2_0, ARG2_1, ARG2_2,
1514ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     ARG2_3, ARG2_4, ARG2_5 );
1515ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1516ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1517ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_RECV:
1518ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* int recv(int s, void *buf, int len, unsigned int flags); */
1519ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* man 2 recv says:
1520ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         The  recv call is normally used only on a connected socket
1521ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         (see connect(2)) and is identical to recvfrom with a  NULL
1522ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         from parameter.
1523ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
1524ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "socketcall.recv(args)", ARG2, 4*sizeof(Addr) );
1525ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(generic_PRE_sys_recv)( tid, ARG2_0, ARG2_1, ARG2_2 );
1526ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1527ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1528ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_CONNECT:
1529ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* int connect(int sockfd,
1530ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                     struct sockaddr *serv_addr, int addrlen ); */
1531ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "socketcall.connect(args)", ARG2, 3*sizeof(Addr) );
1532ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(generic_PRE_sys_connect)( tid, ARG2_0, ARG2_1, ARG2_2 );
1533ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1534ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1535ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_SETSOCKOPT:
1536ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* int setsockopt(int s, int level, int optname,
1537ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        const void *optval, int optlen); */
1538ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "socketcall.setsockopt(args)", ARG2, 5*sizeof(Addr) );
1539ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(generic_PRE_sys_setsockopt)( tid, ARG2_0, ARG2_1, ARG2_2,
1540ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                       ARG2_3, ARG2_4 );
1541ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1542ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1543ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_GETSOCKOPT:
1544ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* int getsockopt(int s, int level, int optname,
1545ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                        void *optval, socklen_t *optlen); */
1546ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "socketcall.getsockopt(args)", ARG2, 5*sizeof(Addr) );
1547ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(linux_PRE_sys_getsockopt)( tid, ARG2_0, ARG2_1, ARG2_2,
1548ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                     ARG2_3, ARG2_4 );
1549ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1550ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1551ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_GETSOCKNAME:
1552ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* int getsockname(int s, struct sockaddr* name, int* namelen) */
1553ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "socketcall.getsockname(args)", ARG2, 3*sizeof(Addr) );
1554ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(generic_PRE_sys_getsockname)( tid, ARG2_0, ARG2_1, ARG2_2 );
1555ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1556ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1557ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_GETPEERNAME:
1558ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* int getpeername(int s, struct sockaddr* name, int* namelen) */
1559ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "socketcall.getpeername(args)", ARG2, 3*sizeof(Addr) );
1560ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(generic_PRE_sys_getpeername)( tid, ARG2_0, ARG2_1, ARG2_2 );
1561ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1562ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1563ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_SHUTDOWN:
1564ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* int shutdown(int s, int how); */
1565ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_READ( "socketcall.shutdown(args)", ARG2, 2*sizeof(Addr) );
1566ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1567ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1568ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_SENDMSG: {
1569ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* int sendmsg(int s, const struct msghdr *msg, int flags); */
1570ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1571ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* this causes warnings, and I don't get why. glibc bug?
1572ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * (after all it's glibc providing the arguments array)
1573ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       PRE_MEM_READ( "socketcall.sendmsg(args)", ARG2, 3*sizeof(Addr) );
1574ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
1575ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(generic_PRE_sys_sendmsg)( tid, ARG2_0, ARG2_1 );
1576ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1577ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1578ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1579ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_RECVMSG: {
1580ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* int recvmsg(int s, struct msghdr *msg, int flags); */
1581ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1582ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* this causes warnings, and I don't get why. glibc bug?
1583ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       * (after all it's glibc providing the arguments array)
1584ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown       PRE_MEM_READ("socketcall.recvmsg(args)", ARG2, 3*sizeof(Addr) );
1585ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      */
1586ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(generic_PRE_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
1587ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1588ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1589ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1590ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
1591ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg,"Warning: unhandled socketcall 0x%lx\n",ARG1);
1592ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SET_STATUS_Failure( VKI_EINVAL );
1593ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1594ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1595ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef ARG2_0
1596ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef ARG2_1
1597ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef ARG2_2
1598ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef ARG2_3
1599ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef ARG2_4
1600ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef ARG2_5
1601ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1602ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1603ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_socketcall)
1604ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1605ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define ARG2_0  (((UWord*)ARG2)[0])
1606ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define ARG2_1  (((UWord*)ARG2)[1])
1607ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define ARG2_2  (((UWord*)ARG2)[2])
1608ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define ARG2_3  (((UWord*)ARG2)[3])
1609ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define ARG2_4  (((UWord*)ARG2)[4])
1610ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  define ARG2_5  (((UWord*)ARG2)[5])
1611ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1612ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   SysRes r;
1613ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   vg_assert(SUCCESS);
1614ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   switch (ARG1 /* request */) {
1615ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1616ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_SOCKETPAIR:
1617ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      r = ML_(generic_POST_sys_socketpair)(
1618ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             tid, VG_(mk_SysRes_Success)(RES),
1619ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown             ARG2_0, ARG2_1, ARG2_2, ARG2_3
1620ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown          );
1621ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SET_STATUS_from_SysRes(r);
1622ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1623ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1624ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_SOCKET:
1625ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      r = ML_(generic_POST_sys_socket)( tid, VG_(mk_SysRes_Success)(RES) );
1626ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SET_STATUS_from_SysRes(r);
1627ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1628ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1629ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_BIND:
1630ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* int bind(int sockfd, struct sockaddr *my_addr,
1631ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown			int addrlen); */
1632ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1633ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1634ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_LISTEN:
1635ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* int listen(int s, int backlog); */
1636ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1637ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1638ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_ACCEPT:
1639ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_ACCEPT4:
1640ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* int accept(int s, struct sockaddr *addr, int *addrlen); */
1641ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      /* int accept4(int s, struct sockaddr *addr, int *addrlen, int flags); */
1642ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     r = ML_(generic_POST_sys_accept)( tid, VG_(mk_SysRes_Success)(RES),
1643ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                            ARG2_0, ARG2_1, ARG2_2 );
1644ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     SET_STATUS_from_SysRes(r);
1645ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     break;
1646ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1647ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_SENDTO:
1648ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1649ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1650ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_SEND:
1651ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1652ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1653ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_RECVFROM:
1654ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(generic_POST_sys_recvfrom)( tid, VG_(mk_SysRes_Success)(RES),
1655ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           ARG2_0, ARG2_1, ARG2_2,
1656ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           ARG2_3, ARG2_4, ARG2_5 );
1657ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1658ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1659ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_RECV:
1660ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(generic_POST_sys_recv)( tid, RES, ARG2_0, ARG2_1, ARG2_2 );
1661ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1662ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1663ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_CONNECT:
1664ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1665ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1666ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_SETSOCKOPT:
1667ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1668ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1669ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_GETSOCKOPT:
1670ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(linux_POST_sys_getsockopt)( tid, VG_(mk_SysRes_Success)(RES),
1671ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      ARG2_0, ARG2_1,
1672ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      ARG2_2, ARG2_3, ARG2_4 );
1673ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1674ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1675ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_GETSOCKNAME:
1676ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(generic_POST_sys_getsockname)( tid, VG_(mk_SysRes_Success)(RES),
1677ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                              ARG2_0, ARG2_1, ARG2_2 );
1678ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1679ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1680ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_GETPEERNAME:
1681ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      ML_(generic_POST_sys_getpeername)( tid, VG_(mk_SysRes_Success)(RES),
1682ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                              ARG2_0, ARG2_1, ARG2_2 );
1683ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1684ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1685ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_SHUTDOWN:
1686ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1687ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1688ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_SENDMSG:
1689ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break;
1690ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1691ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   case VKI_SYS_RECVMSG:
1692ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     ML_(generic_POST_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
1693ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown     break;
1694ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1695ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   default:
1696ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(message)(Vg_DebugMsg,"FATAL: unhandled socketcall 0x%lx\n",ARG1);
1697ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      VG_(core_panic)("... bye!\n");
1698ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      break; /*NOTREACHED*/
1699ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1700ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef ARG2_0
1701ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef ARG2_1
1702ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef ARG2_2
1703ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef ARG2_3
1704ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef ARG2_4
1705ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#  undef ARG2_5
1706ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1707ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1708ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_vm86old)
1709ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1710ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_vm86old ( %#lx )", ARG1);
1711ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ1(int, "vm86old", struct vm86_struct *, info);
1712ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_MEM_WRITE( "vm86old(info)", ARG1, sizeof(struct vki_vm86_struct));
1713ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1714ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1715ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_vm86old)
1716ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1717ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   POST_MEM_WRITE( ARG1, sizeof(struct vki_vm86_struct));
1718ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1719ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1720ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_vm86)
1721ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1722ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRINT("sys_vm86 ( %ld, %#lx )", ARG1,ARG2);
1723ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE_REG_READ2(int, "vm86", unsigned long, fn, struct vm86plus_struct *, v86);
1724ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG1 == VKI_VM86_ENTER || ARG1 == VKI_VM86_ENTER_NO_BYPASS)
1725ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_MEM_WRITE( "vm86(v86)", ARG2, sizeof(struct vki_vm86plus_struct));
1726ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1727ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1728ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_vm86)
1729ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1730ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (ARG1 == VKI_VM86_ENTER || ARG1 == VKI_VM86_ENTER_NO_BYPASS)
1731ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      POST_MEM_WRITE( ARG2, sizeof(struct vki_vm86plus_struct));
1732ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1733ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1734ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1735ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------------------------------------------------------
1736ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PRE/POST wrappers for x86/Linux-variant specific syscalls
1737ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ------------------------------------------------------------ */
1738ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1739ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPRE(sys_syscall223)
1740ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1741ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   Int err;
1742ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1743ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* 223 is used by sys_bproc.  If we're not on a declared bproc
1744ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      variant, fail in the usual way. */
1745ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1746ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (!VG_(strstr)(VG_(clo_kernel_variant), "bproc")) {
1747ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRINT("non-existent syscall! (syscall 223)");
1748ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      PRE_REG_READ0(long, "ni_syscall(223)");
1749ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SET_STATUS_Failure( VKI_ENOSYS );
1750ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
1751ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1752ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1753ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   err = ML_(linux_variant_PRE_sys_bproc)( ARG1, ARG2, ARG3,
1754ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                           ARG4, ARG5, ARG6 );
1755ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (err) {
1756ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SET_STATUS_Failure( err );
1757ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      return;
1758ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
1759ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Let it go through. */
1760ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   *flags |= SfMayBlock; /* who knows?  play safe. */
1761ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1762ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1763ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownPOST(sys_syscall223)
1764ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
1765ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ML_(linux_variant_POST_sys_bproc)( ARG1, ARG2, ARG3,
1766ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown                                      ARG4, ARG5, ARG6 );
1767ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
1768ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1769ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef PRE
1770ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#undef POST
1771ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1772ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1773ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* ---------------------------------------------------------------------
1774ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   The x86/Linux syscall table
1775ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   ------------------------------------------------------------------ */
1776ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1777ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/* Add an x86-linux specific wrapper to a syscall table. */
1778ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PLAX_(sysno, name)    WRAPPER_ENTRY_X_(x86_linux, sysno, name)
1779ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#define PLAXY(sysno, name)    WRAPPER_ENTRY_XY(x86_linux, sysno, name)
1780ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1781ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1782ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// This table maps from __NR_xxx syscall numbers (from
1783ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// linux/include/asm-i386/unistd.h) to the appropriate PRE/POST sys_foo()
1784ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// wrappers on x86 (as per sys_call_table in linux/arch/i386/kernel/entry.S).
1785ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//
1786ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// For those syscalls not handled by Valgrind, the annotation indicate its
1787ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// arch/OS combination, eg. */* (generic), */Linux (Linux only), ?/?
1788ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown// (unknown).
1789ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1790ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brownstatic SyscallTableEntry syscall_table[] = {
1791ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz    //   (restart_syscall)                             // 0
1792ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_exit,              sys_exit),           // 1
1793ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_fork,              sys_fork),           // 2
1794ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_read,              sys_read),           // 3
1795ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_write,             sys_write),          // 4
1796ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1797ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_open,              sys_open),           // 5
1798ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_close,             sys_close),          // 6
1799ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_waitpid,           sys_waitpid),        // 7
1800ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_creat,             sys_creat),          // 8
1801ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_link,              sys_link),           // 9
1802ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1803ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_unlink,            sys_unlink),         // 10
1804ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_execve,            sys_execve),         // 11
1805ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_chdir,             sys_chdir),          // 12
1806ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_time,              sys_time),           // 13
1807ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_mknod,             sys_mknod),          // 14
1808ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1809ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_chmod,             sys_chmod),          // 15
1810ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz    LINX_(__NR_lchown,            sys_lchown16),       // 16
1811ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_break,             sys_ni_syscall),     // 17
1812ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz    //   (__NR_oldstat,           sys_stat),           // 18 (obsolete)
1813ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_lseek,             sys_lseek),          // 19
1814ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1815ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_getpid,            sys_getpid),         // 20
1816ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_mount,             sys_mount),          // 21
1817ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_umount,            sys_oldumount),      // 22
1818ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_setuid,            sys_setuid16),       // 23 ## P
1819ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_getuid,            sys_getuid16),       // 24 ## P
1820ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1821ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_stime,             sys_stime),          // 25 * (SVr4,SVID,X/OPEN)
1822ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PLAXY(__NR_ptrace,            sys_ptrace),         // 26
1823ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_alarm,             sys_alarm),          // 27
1824ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz    //   (__NR_oldfstat,          sys_fstat),          // 28 * L -- obsolete
1825ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_pause,             sys_pause),          // 29
1826ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1827ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_utime,             sys_utime),          // 30
1828ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_stty,              sys_ni_syscall),     // 31
1829ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_gtty,              sys_ni_syscall),     // 32
1830ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_access,            sys_access),         // 33
1831ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_nice,              sys_nice),           // 34
1832ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1833ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_ftime,             sys_ni_syscall),     // 35
1834ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_sync,              sys_sync),           // 36
1835ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_kill,              sys_kill),           // 37
1836ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_rename,            sys_rename),         // 38
1837ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_mkdir,             sys_mkdir),          // 39
1838ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1839ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_rmdir,             sys_rmdir),          // 40
1840ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_dup,               sys_dup),            // 41
1841ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_pipe,              sys_pipe),           // 42
1842ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_times,             sys_times),          // 43
1843ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_prof,              sys_ni_syscall),     // 44
1844ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz
1845ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_brk,               sys_brk),            // 45
1846ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_setgid,            sys_setgid16),       // 46
1847ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_getgid,            sys_getgid16),       // 47
1848ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz    //   (__NR_signal,            sys_signal),         // 48 */* (ANSI C)
1849ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_geteuid,           sys_geteuid16),      // 49
1850ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1851ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_getegid,           sys_getegid16),      // 50
1852ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_acct,              sys_acct),           // 51
1853ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_umount2,           sys_umount),         // 52
1854ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_lock,              sys_ni_syscall),     // 53
1855ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_ioctl,             sys_ioctl),          // 54
1856ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1857ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_fcntl,             sys_fcntl),          // 55
1858ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_mpx,               sys_ni_syscall),     // 56
1859ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_setpgid,           sys_setpgid),        // 57
1860ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_ulimit,            sys_ni_syscall),     // 58
1861ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz    //   (__NR_oldolduname,       sys_olduname),       // 59 Linux -- obsolete
1862ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz
1863ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_umask,             sys_umask),          // 60
1864ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_chroot,            sys_chroot),         // 61
1865ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz    //   (__NR_ustat,             sys_ustat)           // 62 SVr4 -- deprecated
1866ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_dup2,              sys_dup2),           // 63
1867ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_getppid,           sys_getppid),        // 64
1868ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1869ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_getpgrp,           sys_getpgrp),        // 65
1870ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_setsid,            sys_setsid),         // 66
1871d140cf361ba12f3084fbe4a06e8f1a5500bd2285Kenny Root   LINXY(__NR_sigaction,         sys_sigaction),      // 67
1872ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz    //   (__NR_sgetmask,          sys_sgetmask),       // 68 */* (ANSI C)
1873ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz    //   (__NR_ssetmask,          sys_ssetmask),       // 69 */* (ANSI C)
1874ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz
1875ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_setreuid,          sys_setreuid16),     // 70
1876ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_setregid,          sys_setregid16),     // 71
1877d140cf361ba12f3084fbe4a06e8f1a5500bd2285Kenny Root   LINX_(__NR_sigsuspend,        sys_sigsuspend),     // 72
1878ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_sigpending,        sys_sigpending),     // 73
1879ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz    //   (__NR_sethostname,       sys_sethostname),    // 74 */*
1880ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz
1881ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_setrlimit,         sys_setrlimit),      // 75
1882ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_getrlimit,         sys_old_getrlimit),  // 76
1883ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_getrusage,         sys_getrusage),      // 77
1884ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_gettimeofday,      sys_gettimeofday),   // 78
1885ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_settimeofday,      sys_settimeofday),   // 79
1886ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1887ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_getgroups,         sys_getgroups16),    // 80
1888ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_setgroups,         sys_setgroups16),    // 81
1889ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PLAX_(__NR_select,            old_select),         // 82
1890ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_symlink,           sys_symlink),        // 83
1891ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz    //   (__NR_oldlstat,          sys_lstat),          // 84 -- obsolete
1892ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz
1893ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_readlink,          sys_readlink),       // 85
1894ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz    //   (__NR_uselib,            sys_uselib),         // 86 */Linux
1895ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz    //   (__NR_swapon,            sys_swapon),         // 87 */Linux
1896ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz    //   (__NR_reboot,            sys_reboot),         // 88 */Linux
1897ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz    //   (__NR_readdir,           old_readdir),        // 89 -- superseded
1898ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz
1899ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PLAX_(__NR_mmap,              old_mmap),           // 90
1900ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_munmap,            sys_munmap),         // 91
1901ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_truncate,          sys_truncate),       // 92
1902ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_ftruncate,         sys_ftruncate),      // 93
1903ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_fchmod,            sys_fchmod),         // 94
1904ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1905ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_fchown,            sys_fchown16),       // 95
1906ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_getpriority,       sys_getpriority),    // 96
1907ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_setpriority,       sys_setpriority),    // 97
1908ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_profil,            sys_ni_syscall),     // 98
1909ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_statfs,            sys_statfs),         // 99
1910ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1911ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_fstatfs,           sys_fstatfs),        // 100
1912ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_ioperm,            sys_ioperm),         // 101
1913ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PLAXY(__NR_socketcall,        sys_socketcall),     // 102 x86/Linux-only
1914ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_syslog,            sys_syslog),         // 103
1915ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_setitimer,         sys_setitimer),      // 104
1916ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1917ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_getitimer,         sys_getitimer),      // 105
1918ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_stat,              sys_newstat),        // 106
1919ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_lstat,             sys_newlstat),       // 107
1920ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_fstat,             sys_newfstat),       // 108
1921ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz    //   (__NR_olduname,          sys_uname),          // 109 -- obsolete
1922ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz
1923ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_iopl,              sys_iopl),           // 110
1924ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_vhangup,           sys_vhangup),        // 111
1925ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_idle,              sys_ni_syscall),     // 112
1926ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PLAXY(__NR_vm86old,           sys_vm86old),        // 113 x86/Linux-only
1927ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_wait4,             sys_wait4),          // 114
1928ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz
1929ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz    //   (__NR_swapoff,           sys_swapoff),        // 115 */Linux
1930ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_sysinfo,           sys_sysinfo),        // 116
1931ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PLAXY(__NR_ipc,               sys_ipc),            // 117
1932ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_fsync,             sys_fsync),          // 118
1933ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PLAX_(__NR_sigreturn,         sys_sigreturn),      // 119 ?/Linux
1934ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1935ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PLAX_(__NR_clone,             sys_clone),          // 120
1936ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz    //   (__NR_setdomainname,     sys_setdomainname),  // 121 */*(?)
1937ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_uname,             sys_newuname),       // 122
1938ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PLAX_(__NR_modify_ldt,        sys_modify_ldt),     // 123
1939ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_adjtimex,          sys_adjtimex),       // 124
1940ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1941ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_mprotect,          sys_mprotect),       // 125
1942ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_sigprocmask,       sys_sigprocmask),    // 126
1943ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz    // Nb: create_module() was removed 2.4-->2.6
1944ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_create_module,     sys_ni_syscall),     // 127
1945ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_init_module,       sys_init_module),    // 128
1946ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_delete_module,     sys_delete_module),  // 129
1947ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz
1948ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz    // Nb: get_kernel_syms() was removed 2.4-->2.6
1949ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_get_kernel_syms,   sys_ni_syscall),     // 130
1950ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_quotactl,          sys_quotactl),       // 131
1951ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_getpgid,           sys_getpgid),        // 132
1952ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_fchdir,            sys_fchdir),         // 133
1953ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz    //   (__NR_bdflush,           sys_bdflush),        // 134 */Linux
1954ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz
1955ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz    //   (__NR_sysfs,             sys_sysfs),          // 135 SVr4
1956ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_personality,       sys_personality),    // 136
1957ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_afs_syscall,       sys_ni_syscall),     // 137
1958ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_setfsuid,          sys_setfsuid16),     // 138
1959ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_setfsgid,          sys_setfsgid16),     // 139
1960ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1961ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR__llseek,           sys_llseek),         // 140
1962ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_getdents,          sys_getdents),       // 141
1963ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR__newselect,        sys_select),         // 142
1964ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_flock,             sys_flock),          // 143
1965ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_msync,             sys_msync),          // 144
1966ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1967ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_readv,             sys_readv),          // 145
1968ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_writev,            sys_writev),         // 146
1969ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_getsid,            sys_getsid),         // 147
1970ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_fdatasync,         sys_fdatasync),      // 148
1971ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR__sysctl,           sys_sysctl),         // 149
1972ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1973ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_mlock,             sys_mlock),          // 150
1974ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_munlock,           sys_munlock),        // 151
1975ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_mlockall,          sys_mlockall),       // 152
1976ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_munlockall,        sys_munlockall),     // 153
1977ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_sched_setparam,    sys_sched_setparam), // 154
1978ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1979ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_sched_getparam,         sys_sched_getparam),        // 155
1980ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_sched_setscheduler,     sys_sched_setscheduler),    // 156
1981ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_sched_getscheduler,     sys_sched_getscheduler),    // 157
1982ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_sched_yield,            sys_sched_yield),           // 158
1983ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_sched_get_priority_max, sys_sched_get_priority_max),// 159
1984ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1985ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_sched_get_priority_min, sys_sched_get_priority_min),// 160
1986ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_sched_rr_get_interval,  sys_sched_rr_get_interval), // 161
1987ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_nanosleep,         sys_nanosleep),      // 162
1988ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_mremap,            sys_mremap),         // 163
1989ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_setresuid,         sys_setresuid16),    // 164
1990ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
1991ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_getresuid,         sys_getresuid16),    // 165
1992ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PLAXY(__NR_vm86,              sys_vm86),           // 166 x86/Linux-only
1993ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_query_module,      sys_ni_syscall),     // 167
1994ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_poll,              sys_poll),           // 168
1995ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz    //   (__NR_nfsservctl,        sys_nfsservctl),     // 169 */Linux
1996ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz
1997ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_setresgid,         sys_setresgid16),    // 170
1998ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_getresgid,         sys_getresgid16),    // 171
1999ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_prctl,             sys_prctl),          // 172
2000ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PLAX_(__NR_rt_sigreturn,      sys_rt_sigreturn),   // 173 x86/Linux only?
2001ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_rt_sigaction,      sys_rt_sigaction),   // 174
2002ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2003ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_rt_sigprocmask,    sys_rt_sigprocmask), // 175
2004ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_rt_sigpending,     sys_rt_sigpending),  // 176
2005ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_rt_sigtimedwait,   sys_rt_sigtimedwait),// 177
2006ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_rt_sigqueueinfo,   sys_rt_sigqueueinfo),// 178
2007ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_rt_sigsuspend,     sys_rt_sigsuspend),  // 179
2008ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2009ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_pread64,           sys_pread64),        // 180
2010ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_pwrite64,          sys_pwrite64),       // 181
2011ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_chown,             sys_chown16),        // 182
2012ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_getcwd,            sys_getcwd),         // 183
2013ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_capget,            sys_capget),         // 184
2014ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2015ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_capset,            sys_capset),         // 185
2016ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_sigaltstack,       sys_sigaltstack),    // 186
2017ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_sendfile,          sys_sendfile),       // 187
2018ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_getpmsg,           sys_getpmsg),        // 188
2019ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_putpmsg,           sys_putpmsg),        // 189
2020ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2021ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   // Nb: we treat vfork as fork
2022ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_vfork,             sys_fork),           // 190
2023ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_ugetrlimit,        sys_getrlimit),      // 191
2024ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PLAX_(__NR_mmap2,             sys_mmap2),          // 192
2025ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_truncate64,        sys_truncate64),     // 193
2026ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_ftruncate64,       sys_ftruncate64),    // 194
2027ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2028ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PLAXY(__NR_stat64,            sys_stat64),         // 195
2029ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PLAXY(__NR_lstat64,           sys_lstat64),        // 196
2030ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PLAXY(__NR_fstat64,           sys_fstat64),        // 197
2031ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_lchown32,          sys_lchown),         // 198
2032ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_getuid32,          sys_getuid),         // 199
2033ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2034ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_getgid32,          sys_getgid),         // 200
2035ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_geteuid32,         sys_geteuid),        // 201
2036ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_getegid32,         sys_getegid),        // 202
2037ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_setreuid32,        sys_setreuid),       // 203
2038ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_setregid32,        sys_setregid),       // 204
2039ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2040ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_getgroups32,       sys_getgroups),      // 205
2041ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_setgroups32,       sys_setgroups),      // 206
2042ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_fchown32,          sys_fchown),         // 207
2043ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_setresuid32,       sys_setresuid),      // 208
2044ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_getresuid32,       sys_getresuid),      // 209
2045ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2046ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_setresgid32,       sys_setresgid),      // 210
2047ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_getresgid32,       sys_getresgid),      // 211
2048ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_chown32,           sys_chown),          // 212
2049ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_setuid32,          sys_setuid),         // 213
2050ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_setgid32,          sys_setgid),         // 214
2051ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2052ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_setfsuid32,        sys_setfsuid),       // 215
2053ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_setfsgid32,        sys_setfsgid),       // 216
2054ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz    //   (__NR_pivot_root,        sys_pivot_root),     // 217 */Linux
2055ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_mincore,           sys_mincore),        // 218
2056ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_madvise,           sys_madvise),        // 219
2057ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2058ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_getdents64,        sys_getdents64),     // 220
2059ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_fcntl64,           sys_fcntl64),        // 221
2060ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(222,                    sys_ni_syscall),     // 222
2061ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PLAXY(223,                    sys_syscall223),     // 223 // sys_bproc?
2062ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_gettid,            sys_gettid),         // 224
2063ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2064ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_readahead,         sys_readahead),      // 225 */Linux
2065ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_setxattr,          sys_setxattr),       // 226
2066ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_lsetxattr,         sys_lsetxattr),      // 227
2067ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_fsetxattr,         sys_fsetxattr),      // 228
2068ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_getxattr,          sys_getxattr),       // 229
2069ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2070ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_lgetxattr,         sys_lgetxattr),      // 230
2071ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_fgetxattr,         sys_fgetxattr),      // 231
2072ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_listxattr,         sys_listxattr),      // 232
2073ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_llistxattr,        sys_llistxattr),     // 233
2074ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_flistxattr,        sys_flistxattr),     // 234
2075ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2076ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_removexattr,       sys_removexattr),    // 235
2077ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_lremovexattr,      sys_lremovexattr),   // 236
2078ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_fremovexattr,      sys_fremovexattr),   // 237
2079ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_tkill,             sys_tkill),          // 238 */Linux
2080ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_sendfile64,        sys_sendfile64),     // 239
2081ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2082ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_futex,             sys_futex),             // 240
2083ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_sched_setaffinity, sys_sched_setaffinity), // 241
2084ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_sched_getaffinity, sys_sched_getaffinity), // 242
2085ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PLAX_(__NR_set_thread_area,   sys_set_thread_area),   // 243
2086ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PLAX_(__NR_get_thread_area,   sys_get_thread_area),   // 244
2087ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2088ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_io_setup,          sys_io_setup),       // 245
2089ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_io_destroy,        sys_io_destroy),     // 246
2090ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_io_getevents,      sys_io_getevents),   // 247
2091ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_io_submit,         sys_io_submit),      // 248
2092ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_io_cancel,         sys_io_cancel),      // 249
2093ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2094ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_fadvise64,         sys_fadvise64),      // 250 */(Linux?)
2095ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(251,                    sys_ni_syscall),     // 251
2096ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_exit_group,        sys_exit_group),     // 252
2097ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_lookup_dcookie,    sys_lookup_dcookie), // 253
2098ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_epoll_create,      sys_epoll_create),   // 254
2099ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2100ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_epoll_ctl,         sys_epoll_ctl),         // 255
2101ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_epoll_wait,        sys_epoll_wait),        // 256
2102ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//zz    //   (__NR_remap_file_pages,  sys_remap_file_pages),  // 257 */Linux
2103ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_set_tid_address,   sys_set_tid_address),   // 258
2104ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_timer_create,      sys_timer_create),      // 259
2105ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2106ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_timer_settime,     sys_timer_settime),  // (timer_create+1)
2107ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_timer_gettime,     sys_timer_gettime),  // (timer_create+2)
2108ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_timer_getoverrun,  sys_timer_getoverrun),//(timer_create+3)
2109ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_timer_delete,      sys_timer_delete),   // (timer_create+4)
2110ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_clock_settime,     sys_clock_settime),  // (timer_create+5)
2111ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2112ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_clock_gettime,     sys_clock_gettime),  // (timer_create+6)
2113ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_clock_getres,      sys_clock_getres),   // (timer_create+7)
2114ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_clock_nanosleep,   sys_clock_nanosleep),// (timer_create+8) */*
2115ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_statfs64,          sys_statfs64),       // 268
2116ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENXY(__NR_fstatfs64,         sys_fstatfs64),      // 269
2117ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2118ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_tgkill,            sys_tgkill),         // 270 */Linux
2119ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_utimes,            sys_utimes),         // 271
2120ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_fadvise64_64,      sys_fadvise64_64),   // 272 */(Linux?)
2121ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_vserver,           sys_ni_syscall),     // 273
2122ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_mbind,             sys_mbind),          // 274 ?/?
2123ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2124ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_get_mempolicy,     sys_get_mempolicy),  // 275 ?/?
2125ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_set_mempolicy,     sys_set_mempolicy),  // 276 ?/?
2126ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_mq_open,           sys_mq_open),        // 277
2127ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_mq_unlink,         sys_mq_unlink),      // (mq_open+1)
2128ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_mq_timedsend,      sys_mq_timedsend),   // (mq_open+2)
2129ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2130ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_mq_timedreceive,   sys_mq_timedreceive),// (mq_open+3)
2131ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_mq_notify,         sys_mq_notify),      // (mq_open+4)
2132ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_mq_getsetattr,     sys_mq_getsetattr),  // (mq_open+5)
2133ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(__NR_sys_kexec_load,    sys_ni_syscall),     // 283
2134ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_waitid,            sys_waitid),         // 284
2135ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2136ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   GENX_(285,                    sys_ni_syscall),     // 285
2137ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_add_key,           sys_add_key),        // 286
2138ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_request_key,       sys_request_key),    // 287
2139ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_keyctl,            sys_keyctl),         // 288
2140ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_ioprio_set,        sys_ioprio_set),     // 289
2141ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2142ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_ioprio_get,        sys_ioprio_get),     // 290
2143ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_inotify_init,	 sys_inotify_init),   // 291
2144ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_inotify_add_watch, sys_inotify_add_watch), // 292
2145ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_inotify_rm_watch,	 sys_inotify_rm_watch), // 293
2146ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   LINX_(__NR_migrate_pages,	 sys_migrate_pages),    // 294
2147ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2148ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_openat,		 sys_openat),           // 295
2149ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_mkdirat,		 sys_mkdirat),          // 296
2150ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_mknodat,		 sys_mknodat),          // 297
2151ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_fchownat,		 sys_fchownat),         // 298
2152ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_futimesat,	 sys_futimesat),        // 299
2153ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2154ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   PLAXY(__NR_fstatat64,	 sys_fstatat64),        // 300
2155ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_unlinkat,		 sys_unlinkat),         // 301
2156ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_renameat,		 sys_renameat),         // 302
2157ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_linkat,		 sys_linkat),           // 303
2158ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_symlinkat,	 sys_symlinkat),        // 304
2159ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2160ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_readlinkat,	 sys_readlinkat),       // 305
2161ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_fchmodat,		 sys_fchmodat),         // 306
2162ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_faccessat,	 sys_faccessat),        // 307
2163ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_pselect6,		 sys_pselect6),         // 308
2164ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_ppoll,		 sys_ppoll),            // 309
2165ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2166ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   LINX_(__NR_unshare,		 sys_unshare),          // 310
2167ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_set_robust_list,	 sys_set_robust_list),  // 311
2168ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_get_robust_list,	 sys_get_robust_list),  // 312
2169ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_splice,            sys_splice),           // 313
2170ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_sync_file_range,   sys_sync_file_range),  // 314
2171ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2172ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   LINX_(__NR_tee,               sys_ni_syscall),       // 315
2173ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   LINX_(__NR_vmsplice,          sys_ni_syscall),       // 316
2174ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown//   LINX_(__NR_move_pages,        sys_ni_syscall),       // 317
2175ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_getcpu,            sys_getcpu),           // 318
2176ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_epoll_pwait,       sys_epoll_pwait),      // 319
2177ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2178ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_utimensat,         sys_utimensat),        // 320
2179ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_signalfd,          sys_signalfd),         // 321
2180ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_timerfd_create,    sys_timerfd_create),   // 322
2181ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_eventfd,           sys_eventfd),          // 323
2182ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_fallocate,         sys_fallocate),        // 324
2183ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2184ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_timerfd_settime,   sys_timerfd_settime),  // 325
2185ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_timerfd_gettime,   sys_timerfd_gettime),  // 326
2186ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_signalfd4,         sys_signalfd4),        // 327
2187ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_eventfd2,          sys_eventfd2),         // 328
2188ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_epoll_create1,     sys_epoll_create1),     // 329
2189ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2190ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_dup3,              sys_dup3),             // 330
2191ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_pipe2,             sys_pipe2),            // 331
2192ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_inotify_init1,     sys_inotify_init1),    // 332
2193ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_preadv,            sys_preadv),           // 333
2194ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINX_(__NR_pwritev,           sys_pwritev),          // 334
2195ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2196ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo),// 335
2197ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   LINXY(__NR_perf_counter_open, sys_perf_counter_open) // 336
2198ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown};
2199ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2200ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff BrownSyscallTableEntry* ML_(get_linux_syscall_entry) ( UInt sysno )
2201ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown{
2202ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   const UInt syscall_table_size
2203ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      = sizeof(syscall_table) / sizeof(syscall_table[0]);
2204ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2205ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Is it in the contiguous initial section of the table? */
2206ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   if (sysno < syscall_table_size) {
2207ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      SyscallTableEntry* sys = &syscall_table[sysno];
2208ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      if (sys->before == NULL)
2209ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return NULL; /* no entry */
2210ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown      else
2211ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown         return sys;
2212ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   }
2213ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2214ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   /* Can't find a wrapper */
2215ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown   return NULL;
2216ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown}
2217ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2218ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown#endif // defined(VGP_x86_linux)
2219ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown
2220ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
2221ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--- end                                                          ---*/
2222ed07e00d438c74b7a23c01bfffde77e3968305e4Jeff Brown/*--------------------------------------------------------------------*/
2223