blob: caa1e2836b3a438631ec21af18ed5f63b730cf78 [file] [log] [blame]
nethercote41c75da2004-10-18 15:34:14 +00001
2/*--------------------------------------------------------------------*/
njnc1b01812005-06-17 22:19:06 +00003/*--- Platform-specific syscalls stuff. syswrap-x86-linux.c ---*/
nethercote41c75da2004-10-18 15:34:14 +00004/*--------------------------------------------------------------------*/
5
6/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
nethercote41c75da2004-10-18 15:34:14 +00009
njn53612422005-03-12 16:22:54 +000010 Copyright (C) 2000-2005 Nicholas Nethercote
njn2bc10122005-05-08 02:10:27 +000011 njn@valgrind.org
nethercote41c75da2004-10-18 15:34:14 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
sewardjb5f6f512005-03-10 23:59:00 +000031/* TODO/FIXME jrs 20050207: assignments to the syscall return result
32 in interrupted_syscall() need to be reviewed. They don't seem
33 to assign the shadow state.
34*/
35
njnc7561b92005-06-19 01:24:32 +000036#include "pub_core_basics.h"
37#include "pub_core_threadstate.h"
sewardj45f4e7c2005-09-27 19:20:21 +000038#include "pub_core_debuginfo.h" // VG_(di_notify_mmap)
sewardj55f9d1a2005-04-25 11:11:44 +000039#include "pub_core_aspacemgr.h"
njn899ce732005-06-21 00:28:11 +000040#include "pub_core_debuglog.h"
sewardja8d8e232005-06-07 20:04:56 +000041#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000042#include "pub_core_libcassert.h"
njn36a20fa2005-06-03 03:08:39 +000043#include "pub_core_libcprint.h"
njnf39e9a32005-06-12 02:43:17 +000044#include "pub_core_libcproc.h"
njnde62cbf2005-06-10 22:08:14 +000045#include "pub_core_libcsignal.h"
njnaf1d7df2005-06-11 01:31:52 +000046#include "pub_core_mallocfree.h"
njnf4c50162005-06-20 14:18:12 +000047#include "pub_core_options.h"
njnc7561b92005-06-19 01:24:32 +000048#include "pub_core_scheduler.h"
njnf4c50162005-06-20 14:18:12 +000049#include "pub_core_sigframe.h" // For VG_(sigframe_destroy)()
njnde62cbf2005-06-10 22:08:14 +000050#include "pub_core_signals.h"
njn9abd6082005-06-17 21:31:45 +000051#include "pub_core_syscall.h"
njnc1b01812005-06-17 22:19:06 +000052#include "pub_core_syswrap.h"
njn43b9a8a2005-05-10 04:37:01 +000053#include "pub_core_tooliface.h"
sewardja8d8e232005-06-07 20:04:56 +000054
55#include "priv_types_n_macros.h"
njnc1b01812005-06-17 22:19:06 +000056#include "priv_syswrap-generic.h" /* for decls of generic wrappers */
57#include "priv_syswrap-linux.h" /* for decls of linux-ish wrappers */
sewardjce5a5662005-10-06 03:19:49 +000058#include "priv_syswrap-linux-variants.h" /* decls of linux variant wrappers */
njnc1b01812005-06-17 22:19:06 +000059#include "priv_syswrap-main.h"
sewardja8d8e232005-06-07 20:04:56 +000060
61#include "vki_unistd.h" /* for the __NR_* constants */
sewardj55f9d1a2005-04-25 11:11:44 +000062
sewardj4d89e302005-03-16 22:04:40 +000063
64/* ---------------------------------------------------------------------
njn2335d112005-05-15 20:52:04 +000065 Stacks, thread wrappers
sewardj4d89e302005-03-16 22:04:40 +000066 Note. Why is this stuff here?
67 ------------------------------------------------------------------ */
68
sewardj45f4e7c2005-09-27 19:20:21 +000069/* Allocate a stack for this thread. They're allocated lazily, and
70 never freed. */
sewardjb5f6f512005-03-10 23:59:00 +000071
sewardj45f4e7c2005-09-27 19:20:21 +000072/* Allocate a stack for this thread, if it doesn't already have one.
73 Returns the initial stack pointer value to use, or 0 if allocation
74 failed. */
sewardjb5f6f512005-03-10 23:59:00 +000075
sewardj45f4e7c2005-09-27 19:20:21 +000076static Addr allocstack ( ThreadId tid )
sewardjb5f6f512005-03-10 23:59:00 +000077{
sewardj45f4e7c2005-09-27 19:20:21 +000078 ThreadState* tst = VG_(get_ThreadState)(tid);
79 VgStack* stack;
80 Addr initial_SP;
81
82 /* Either the stack_base and stack_init_SP are both zero (in which
83 case a stack hasn't been allocated) or they are both non-zero,
84 in which case it has. */
85
86 if (tst->os_state.valgrind_stack_base == 0)
87 vg_assert(tst->os_state.valgrind_stack_init_SP == 0);
88
89 if (tst->os_state.valgrind_stack_base != 0)
90 vg_assert(tst->os_state.valgrind_stack_init_SP != 0);
91
92 /* If no stack is present, allocate one. */
sewardjb5f6f512005-03-10 23:59:00 +000093
njn990e90c2005-04-05 02:49:09 +000094 if (tst->os_state.valgrind_stack_base == 0) {
sewardj45f4e7c2005-09-27 19:20:21 +000095 stack = VG_(am_alloc_VgStack)( &initial_SP );
96 if (stack) {
97 tst->os_state.valgrind_stack_base = (Addr)stack;
98 tst->os_state.valgrind_stack_init_SP = initial_SP;
99 }
sewardjb5f6f512005-03-10 23:59:00 +0000100 }
101
sewardjb5f6f512005-03-10 23:59:00 +0000102 if (0)
sewardj45f4e7c2005-09-27 19:20:21 +0000103 VG_(printf)( "stack for tid %d at %p; init_SP=%p\n",
104 tid,
105 (void*)tst->os_state.valgrind_stack_base,
106 (void*)tst->os_state.valgrind_stack_init_SP );
107
108 return tst->os_state.valgrind_stack_init_SP;
sewardjb5f6f512005-03-10 23:59:00 +0000109}
110
sewardj1d887112005-05-30 21:44:08 +0000111
112/* Run a thread all the way to the end, then do appropriate exit actions
113 (this is the last-one-out-turn-off-the-lights bit).
114*/
115static void run_a_thread_NORETURN ( Word tidW )
sewardjb5f6f512005-03-10 23:59:00 +0000116{
sewardj1d887112005-05-30 21:44:08 +0000117 ThreadId tid = (ThreadId)tidW;
tomd4561962005-10-12 10:50:56 +0000118 VgSchedReturnCode src;
119 Int c;
sewardj1d887112005-05-30 21:44:08 +0000120
njnc1b01812005-06-17 22:19:06 +0000121 VG_(debugLog)(1, "syswrap-x86-linux",
sewardj1d887112005-05-30 21:44:08 +0000122 "run_a_thread_NORETURN(tid=%lld): "
cerion7b2c38c2005-06-23 07:52:54 +0000123 "ML_(thread_wrapper) called\n",
sewardj1d887112005-05-30 21:44:08 +0000124 (ULong)tidW);
125
126 /* Run the thread all the way through. */
tomd4561962005-10-12 10:50:56 +0000127 src = ML_(thread_wrapper)(tid);
sewardj1d887112005-05-30 21:44:08 +0000128
njnc1b01812005-06-17 22:19:06 +0000129 VG_(debugLog)(1, "syswrap-x86-linux",
sewardj1d887112005-05-30 21:44:08 +0000130 "run_a_thread_NORETURN(tid=%lld): "
cerion7b2c38c2005-06-23 07:52:54 +0000131 "ML_(thread_wrapper) done\n",
sewardj1d887112005-05-30 21:44:08 +0000132 (ULong)tidW);
133
tomd4561962005-10-12 10:50:56 +0000134 c = VG_(count_living_threads)();
sewardj1d887112005-05-30 21:44:08 +0000135 vg_assert(c >= 1); /* stay sane */
136
137 if (c == 1) {
138
njnc1b01812005-06-17 22:19:06 +0000139 VG_(debugLog)(1, "syswrap-x86-linux",
sewardj1d887112005-05-30 21:44:08 +0000140 "run_a_thread_NORETURN(tid=%lld): "
141 "last one standing\n",
142 (ULong)tidW);
143
144 /* We are the last one standing. Keep hold of the lock and
sewardj1ae3f3a2005-09-28 10:47:38 +0000145 carry on to show final tool results, then exit the entire system.
146 Use the continuation pointer set at startup in m_main. */
147 ( * VG_(address_of_m_main_shutdown_actions_NORETURN) ) (tid, src);
sewardj1d887112005-05-30 21:44:08 +0000148
149 } else {
150
tomd4561962005-10-12 10:50:56 +0000151 ThreadState *tst;
152
njnc1b01812005-06-17 22:19:06 +0000153 VG_(debugLog)(1, "syswrap-x86-linux",
sewardj1d887112005-05-30 21:44:08 +0000154 "run_a_thread_NORETURN(tid=%lld): "
155 "not last one standing\n",
156 (ULong)tidW);
157
158 /* OK, thread is dead, but others still exist. Just exit. */
tomd4561962005-10-12 10:50:56 +0000159 tst = VG_(get_ThreadState)(tid);
sewardj1d887112005-05-30 21:44:08 +0000160
161 /* This releases the run lock */
162 VG_(exit_thread)(tid);
163 vg_assert(tst->status == VgTs_Zombie);
164
165 /* We have to use this sequence to terminate the thread to
166 prevent a subtle race. If VG_(exit_thread)() had left the
167 ThreadState as Empty, then it could have been reallocated,
168 reusing the stack while we're doing these last cleanups.
169 Instead, VG_(exit_thread) leaves it as Zombie to prevent
170 reallocation. We need to make sure we don't touch the stack
171 between marking it Empty and exiting. Hence the
172 assembler. */
173 asm volatile (
174 "movl %1, %0\n" /* set tst->status = VgTs_Empty */
175 "movl %2, %%eax\n" /* set %eax = __NR_exit */
176 "movl %3, %%ebx\n" /* set %ebx = tst->os_state.exitcode */
177 "int $0x80\n" /* exit(tst->os_state.exitcode) */
178 : "=m" (tst->status)
179 : "n" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode));
180
181 VG_(core_panic)("Thread exit failed?\n");
182 }
183
184 /*NOTREACHED*/
185 vg_assert(0);
186}
187
188
njnfcb7c3e2005-06-18 15:54:25 +0000189/* Call f(arg1), but first switch stacks, using 'stack' as the new
190 stack, and use 'retaddr' as f's return-to address. Also, clear all
191 the integer registers before entering f.*/
192__attribute__((noreturn))
193void call_on_new_stack_0_1 ( Addr stack,
194 Addr retaddr,
195 void (*f)(Word),
196 Word arg1 );
197// 4(%esp) == stack
198// 8(%esp) == retaddr
199// 12(%esp) == f
200// 16(%esp) == arg1
201asm(
202"call_on_new_stack_0_1:\n"
203" movl %esp, %esi\n" // remember old stack pointer
204" movl 4(%esi), %esp\n" // set stack
205" pushl 16(%esi)\n" // arg1 to stack
206" pushl 8(%esi)\n" // retaddr to stack
207" pushl 12(%esi)\n" // f to stack
208" movl $0, %eax\n" // zero all GP regs
209" movl $0, %ebx\n"
210" movl $0, %ecx\n"
211" movl $0, %edx\n"
212" movl $0, %esi\n"
213" movl $0, %edi\n"
214" movl $0, %ebp\n"
215" ret\n" // jump to f
216" ud2\n" // should never get here
217);
218
219
sewardj45f4e7c2005-09-27 19:20:21 +0000220/* Allocate a stack for the main thread, and run it all the way to the
221 end. Although we already have a working VgStack
sewardj98eee482005-09-29 10:24:17 +0000222 (VG_(interim_stack)) it's better to allocate a new one, so that
sewardj45f4e7c2005-09-27 19:20:21 +0000223 overflow detection works uniformly for all threads.
sewardj1d887112005-05-30 21:44:08 +0000224*/
njnaf839f52005-06-23 03:27:57 +0000225void VG_(main_thread_wrapper_NORETURN)(ThreadId tid)
sewardj1d887112005-05-30 21:44:08 +0000226{
tomd4561962005-10-12 10:50:56 +0000227 Addr esp;
228
njnc1b01812005-06-17 22:19:06 +0000229 VG_(debugLog)(1, "syswrap-x86-linux",
njnaf839f52005-06-23 03:27:57 +0000230 "entering VG_(main_thread_wrapper_NORETURN)\n");
sewardj1d887112005-05-30 21:44:08 +0000231
tomd4561962005-10-12 10:50:56 +0000232 esp = allocstack(tid);
sewardj45f4e7c2005-09-27 19:20:21 +0000233
234 /* If we can't even allocate the first thread's stack, we're hosed.
235 Give up. */
236 vg_assert2(esp != 0, "Cannot allocate main thread's stack.");
sewardjb5f6f512005-03-10 23:59:00 +0000237
sewardj1d887112005-05-30 21:44:08 +0000238 /* shouldn't be any other threads around yet */
239 vg_assert( VG_(count_living_threads)() == 1 );
sewardjb5f6f512005-03-10 23:59:00 +0000240
sewardj7f082a62005-03-22 01:55:35 +0000241 call_on_new_stack_0_1(
sewardj45f4e7c2005-09-27 19:20:21 +0000242 esp, /* stack */
sewardj1d887112005-05-30 21:44:08 +0000243 0, /*bogus return address*/
244 run_a_thread_NORETURN, /* fn to call */
245 (Word)tid /* arg to give it */
sewardj7f082a62005-03-22 01:55:35 +0000246 );
247
248 /*NOTREACHED*/
249 vg_assert(0);
sewardjb5f6f512005-03-10 23:59:00 +0000250}
251
sewardj1d887112005-05-30 21:44:08 +0000252
253static Int start_thread_NORETURN ( void* arg )
sewardjb5f6f512005-03-10 23:59:00 +0000254{
sewardj1d887112005-05-30 21:44:08 +0000255 ThreadState* tst = (ThreadState*)arg;
256 ThreadId tid = tst->tid;
sewardjb5f6f512005-03-10 23:59:00 +0000257
sewardj1d887112005-05-30 21:44:08 +0000258 run_a_thread_NORETURN ( (Word)tid );
259 /*NOTREACHED*/
260 vg_assert(0);
sewardjb5f6f512005-03-10 23:59:00 +0000261}
262
sewardj1d887112005-05-30 21:44:08 +0000263
njn2335d112005-05-15 20:52:04 +0000264/* ---------------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +0000265 clone() handling
njn2335d112005-05-15 20:52:04 +0000266 ------------------------------------------------------------------ */
sewardjb5f6f512005-03-10 23:59:00 +0000267
sewardja8d8e232005-06-07 20:04:56 +0000268/*
269 Perform a clone system call. clone is strange because it has
270 fork()-like return-twice semantics, so it needs special
271 handling here.
272
273 Upon entry, we have:
274
275 int (fn)(void*) in 0+FSZ(%esp)
276 void* child_stack in 4+FSZ(%esp)
277 int flags in 8+FSZ(%esp)
278 void* arg in 12+FSZ(%esp)
279 pid_t* child_tid in 16+FSZ(%esp)
280 pid_t* parent_tid in 20+FSZ(%esp)
281 void* tls_ptr in 24+FSZ(%esp)
282
283 System call requires:
284
285 int $__NR_clone in %eax
286 int flags in %ebx
287 void* child_stack in %ecx
288 pid_t* parent_tid in %edx
289 pid_t* child_tid in %edi
290 void* tls_ptr in %esi
291
292 Returns an Int encoded in the linux-x86 way, not a SysRes.
293 */
tomf5d62be2005-07-18 12:02:45 +0000294#define FSZ "4+4+4+4" /* frame size = retaddr+ebx+edi+esi */
sewardj7d15e512005-09-30 01:20:47 +0000295#define __NR_CLONE VG_STRINGIFY(__NR_clone)
296#define __NR_EXIT VG_STRINGIFY(__NR_exit)
sewardja8d8e232005-06-07 20:04:56 +0000297
298extern
299Int do_syscall_clone_x86_linux ( Int (*fn)(void *),
300 void* stack,
301 Int flags,
302 void* arg,
303 Int* child_tid,
304 Int* parent_tid,
305 vki_modify_ldt_t * );
306asm(
307"\n"
308"do_syscall_clone_x86_linux:\n"
309" push %ebx\n"
310" push %edi\n"
tomf5d62be2005-07-18 12:02:45 +0000311" push %esi\n"
sewardja8d8e232005-06-07 20:04:56 +0000312
313 /* set up child stack with function and arg */
314" movl 4+"FSZ"(%esp), %ecx\n" /* syscall arg2: child stack */
315" movl 12+"FSZ"(%esp), %ebx\n" /* fn arg */
316" movl 0+"FSZ"(%esp), %eax\n" /* fn */
317" lea -8(%ecx), %ecx\n" /* make space on stack */
318" movl %ebx, 4(%ecx)\n" /* fn arg */
319" movl %eax, 0(%ecx)\n" /* fn */
320
321 /* get other args to clone */
322" movl 8+"FSZ"(%esp), %ebx\n" /* syscall arg1: flags */
323" movl 20+"FSZ"(%esp), %edx\n" /* syscall arg3: parent tid * */
tomb33fc682005-07-19 23:01:56 +0000324" movl 16+"FSZ"(%esp), %edi\n" /* syscall arg5: child tid * */
325" movl 24+"FSZ"(%esp), %esi\n" /* syscall arg4: tls_ptr * */
sewardja8d8e232005-06-07 20:04:56 +0000326" movl $"__NR_CLONE", %eax\n"
327" int $0x80\n" /* clone() */
328" testl %eax, %eax\n" /* child if retval == 0 */
329" jnz 1f\n"
330
331 /* CHILD - call thread function */
332" popl %eax\n"
333" call *%eax\n" /* call fn */
334
335 /* exit with result */
336" movl %eax, %ebx\n" /* arg1: return value from fn */
337" movl $"__NR_EXIT", %eax\n"
338" int $0x80\n"
339
340 /* Hm, exit returned */
341" ud2\n"
342
sewardje7aa4ae2005-06-09 12:43:42 +0000343"1:\n" /* PARENT or ERROR */
tomf5d62be2005-07-18 12:02:45 +0000344" pop %esi\n"
sewardja8d8e232005-06-07 20:04:56 +0000345" pop %edi\n"
346" pop %ebx\n"
347" ret\n"
348);
349
350#undef FSZ
351#undef __NR_CLONE
352#undef __NR_EXIT
sewardja8d8e232005-06-07 20:04:56 +0000353
sewardje7aa4ae2005-06-09 12:43:42 +0000354
njn2335d112005-05-15 20:52:04 +0000355// forward declarations
sewardj468dc792005-05-31 10:12:06 +0000356static void setup_child ( ThreadArchState*, ThreadArchState*, Bool );
sewardja8d8e232005-06-07 20:04:56 +0000357static SysRes sys_set_thread_area ( ThreadId, vki_modify_ldt_t* );
njn2335d112005-05-15 20:52:04 +0000358
359/*
sewardjb5f6f512005-03-10 23:59:00 +0000360 When a client clones, we need to keep track of the new thread. This means:
361 1. allocate a ThreadId+ThreadState+stack for the the thread
362
363 2. initialize the thread's new VCPU state
364
365 3. create the thread using the same args as the client requested,
366 but using the scheduler entrypoint for EIP, and a separate stack
367 for ESP.
368 */
sewardja8d8e232005-06-07 20:04:56 +0000369static SysRes do_clone ( ThreadId ptid,
370 UInt flags, Addr esp,
sewardje7aa4ae2005-06-09 12:43:42 +0000371 Int* parent_tidptr,
372 Int* child_tidptr,
sewardja8d8e232005-06-07 20:04:56 +0000373 vki_modify_ldt_t *tlsinfo)
sewardjb5f6f512005-03-10 23:59:00 +0000374{
375 static const Bool debug = False;
376
sewardja8d8e232005-06-07 20:04:56 +0000377 ThreadId ctid = VG_(alloc_ThreadState)();
378 ThreadState* ptst = VG_(get_ThreadState)(ptid);
379 ThreadState* ctst = VG_(get_ThreadState)(ctid);
380 UWord* stack;
sewardj45f4e7c2005-09-27 19:20:21 +0000381 NSegment* seg;
sewardja8d8e232005-06-07 20:04:56 +0000382 SysRes res;
383 Int eax;
sewardjb5f6f512005-03-10 23:59:00 +0000384 vki_sigset_t blockall, savedmask;
385
386 VG_(sigfillset)(&blockall);
387
388 vg_assert(VG_(is_running_thread)(ptid));
389 vg_assert(VG_(is_valid_tid)(ctid));
390
sewardj45f4e7c2005-09-27 19:20:21 +0000391 stack = (UWord*)allocstack(ctid);
392 if (stack == NULL) {
393 res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
394 goto out;
395 }
sewardjb5f6f512005-03-10 23:59:00 +0000396
397 /* Copy register state
398
399 Both parent and child return to the same place, and the code
400 following the clone syscall works out which is which, so we
401 don't need to worry about it.
402
403 The parent gets the child's new tid returned from clone, but the
404 child gets 0.
405
406 If the clone call specifies a NULL esp for the new thread, then
407 it actually gets a copy of the parent's esp.
408 */
sewardj3d7c2f02005-07-24 07:15:44 +0000409 /* Note: the clone call done by the Quadrics Elan3 driver specifies
sewardj468dc792005-05-31 10:12:06 +0000410 clone flags of 0xF00, and it seems to rely on the assumption
sewardj3d7c2f02005-07-24 07:15:44 +0000411 that the child inherits a copy of the parent's GDT.
412 setup_child takes care of setting that up. */
413 setup_child( &ctst->arch, &ptst->arch, True );
sewardjb5f6f512005-03-10 23:59:00 +0000414
sewardje7aa4ae2005-06-09 12:43:42 +0000415 /* Make sys_clone appear to have returned Success(0) in the
416 child. */
sewardja8d8e232005-06-07 20:04:56 +0000417 ctst->arch.vex.guest_EAX = 0;
418
sewardjb5f6f512005-03-10 23:59:00 +0000419 if (esp != 0)
420 ctst->arch.vex.guest_ESP = esp;
421
422 ctst->os_state.parent = ptid;
sewardjb5f6f512005-03-10 23:59:00 +0000423
424 /* inherit signal mask */
njnaffd8782005-05-18 22:56:00 +0000425 ctst->sig_mask = ptst->sig_mask;
sewardjb5f6f512005-03-10 23:59:00 +0000426 ctst->tmp_sig_mask = ptst->sig_mask;
427
428 /* We don't really know where the client stack is, because its
429 allocated by the client. The best we can do is look at the
430 memory mappings and try to derive some useful information. We
431 assume that esp starts near its highest possible value, and can
432 only go down to the start of the mmaped segment. */
sewardj45f4e7c2005-09-27 19:20:21 +0000433 seg = VG_(am_find_nsegment)((Addr)esp);
434 if (seg && seg->kind != SkResvn) {
njn13bfd852005-06-02 03:52:53 +0000435 ctst->client_stack_highest_word = (Addr)VG_PGROUNDUP(esp);
sewardj45f4e7c2005-09-27 19:20:21 +0000436 ctst->client_stack_szB = ctst->client_stack_highest_word - seg->start;
sewardjb5f6f512005-03-10 23:59:00 +0000437
438 if (debug)
439 VG_(printf)("tid %d: guessed client stack range %p-%p\n",
sewardj45f4e7c2005-09-27 19:20:21 +0000440 ctid, seg->start, VG_PGROUNDUP(esp));
sewardjb5f6f512005-03-10 23:59:00 +0000441 } else {
442 VG_(message)(Vg_UserMsg, "!? New thread %d starts with ESP(%p) unmapped\n",
443 ctid, esp);
njn50ba34e2005-04-04 02:41:42 +0000444 ctst->client_stack_szB = 0;
sewardjb5f6f512005-03-10 23:59:00 +0000445 }
446
447 if (flags & VKI_CLONE_SETTLS) {
448 if (debug)
sewardja8d8e232005-06-07 20:04:56 +0000449 VG_(printf)("clone child has SETTLS: tls info at %p: idx=%d "
450 "base=%p limit=%x; esp=%p fs=%x gs=%x\n",
451 tlsinfo, tlsinfo->entry_number,
452 tlsinfo->base_addr, tlsinfo->limit,
sewardjb5f6f512005-03-10 23:59:00 +0000453 ptst->arch.vex.guest_ESP,
454 ctst->arch.vex.guest_FS, ctst->arch.vex.guest_GS);
sewardja8d8e232005-06-07 20:04:56 +0000455 res = sys_set_thread_area(ctid, tlsinfo);
456 if (res.isError)
sewardjb5f6f512005-03-10 23:59:00 +0000457 goto out;
458 }
459
460 flags &= ~VKI_CLONE_SETTLS;
461
462 /* start the thread with everything blocked */
463 VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
464
465 /* Create the new thread */
sewardja8d8e232005-06-07 20:04:56 +0000466 eax = do_syscall_clone_x86_linux(
467 start_thread_NORETURN, stack, flags, &VG_(threads)[ctid],
468 child_tidptr, parent_tidptr, NULL
469 );
cerion85665ca2005-06-20 15:51:07 +0000470 res = VG_(mk_SysRes_x86_linux)( eax );
sewardje7aa4ae2005-06-09 12:43:42 +0000471
sewardjb5f6f512005-03-10 23:59:00 +0000472 VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
473
474 out:
sewardja8d8e232005-06-07 20:04:56 +0000475 if (res.isError) {
sewardjb5f6f512005-03-10 23:59:00 +0000476 /* clone failed */
njnaf839f52005-06-23 03:27:57 +0000477 VG_(cleanup_thread)(&ctst->arch);
sewardjb5f6f512005-03-10 23:59:00 +0000478 ctst->status = VgTs_Empty;
479 }
480
sewardja8d8e232005-06-07 20:04:56 +0000481 return res;
sewardjb5f6f512005-03-10 23:59:00 +0000482}
483
sewardja8d8e232005-06-07 20:04:56 +0000484
sewardjb5f6f512005-03-10 23:59:00 +0000485/* Do a clone which is really a fork() */
sewardja8d8e232005-06-07 20:04:56 +0000486static SysRes do_fork_clone ( ThreadId tid,
487 UInt flags, Addr esp,
488 Int* parent_tidptr,
489 Int* child_tidptr )
sewardjb5f6f512005-03-10 23:59:00 +0000490{
491 vki_sigset_t fork_saved_mask;
492 vki_sigset_t mask;
sewardja8d8e232005-06-07 20:04:56 +0000493 SysRes res;
sewardjb5f6f512005-03-10 23:59:00 +0000494
sewardja8d8e232005-06-07 20:04:56 +0000495 if (flags & (VKI_CLONE_SETTLS | VKI_CLONE_FS | VKI_CLONE_VM
496 | VKI_CLONE_FILES | VKI_CLONE_VFORK))
497 return VG_(mk_SysRes_Error)( VKI_EINVAL );
sewardjb5f6f512005-03-10 23:59:00 +0000498
499 /* Block all signals during fork, so that we can fix things up in
500 the child without being interrupted. */
501 VG_(sigfillset)(&mask);
502 VG_(sigprocmask)(VKI_SIG_SETMASK, &mask, &fork_saved_mask);
503
sewardjb5f6f512005-03-10 23:59:00 +0000504 /* Since this is the fork() form of clone, we don't need all that
505 VG_(clone) stuff */
sewardje7aa4ae2005-06-09 12:43:42 +0000506 res = VG_(do_syscall5)( __NR_clone, flags,
507 (UWord)NULL, (UWord)parent_tidptr,
508 (UWord)NULL, (UWord)child_tidptr );
sewardjb5f6f512005-03-10 23:59:00 +0000509
sewardja8d8e232005-06-07 20:04:56 +0000510 if (!res.isError && res.val == 0) {
sewardjb5f6f512005-03-10 23:59:00 +0000511 /* child */
512 VG_(do_atfork_child)(tid);
513
514 /* restore signal mask */
515 VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
sewardja8d8e232005-06-07 20:04:56 +0000516 }
517 else
518 if (!res.isError && res.val > 0) {
sewardjb5f6f512005-03-10 23:59:00 +0000519 /* parent */
520 if (VG_(clo_trace_syscalls))
sewardja8d8e232005-06-07 20:04:56 +0000521 VG_(printf)(" clone(fork): process %d created child %d\n",
522 VG_(getpid)(), res.val);
sewardjb5f6f512005-03-10 23:59:00 +0000523
sewardjb5f6f512005-03-10 23:59:00 +0000524 /* restore signal mask */
525 VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
526 }
527
sewardja8d8e232005-06-07 20:04:56 +0000528 return res;
sewardjb5f6f512005-03-10 23:59:00 +0000529}
530
nethercote8ff888f2004-11-17 17:11:45 +0000531/* ---------------------------------------------------------------------
njn2335d112005-05-15 20:52:04 +0000532 LDT/GDT simulation
533 ------------------------------------------------------------------ */
534
535/* Details of the LDT simulation
536 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
537
538 When a program runs natively, the linux kernel allows each *thread*
539 in it to have its own LDT. Almost all programs never do this --
540 it's wildly unportable, after all -- and so the kernel never
541 allocates the structure, which is just as well as an LDT occupies
542 64k of memory (8192 entries of size 8 bytes).
543
544 A thread may choose to modify its LDT entries, by doing the
545 __NR_modify_ldt syscall. In such a situation the kernel will then
546 allocate an LDT structure for it. Each LDT entry is basically a
547 (base, limit) pair. A virtual address in a specific segment is
548 translated to a linear address by adding the segment's base value.
549 In addition, the virtual address must not exceed the limit value.
550
551 To use an LDT entry, a thread loads one of the segment registers
552 (%cs, %ss, %ds, %es, %fs, %gs) with the index of the LDT entry (0
553 .. 8191) it wants to use. In fact, the required value is (index <<
554 3) + 7, but that's not important right now. Any normal instruction
555 which includes an addressing mode can then be made relative to that
556 LDT entry by prefixing the insn with a so-called segment-override
557 prefix, a byte which indicates which of the 6 segment registers
558 holds the LDT index.
559
560 Now, a key constraint is that valgrind's address checks operate in
561 terms of linear addresses. So we have to explicitly translate
562 virtual addrs into linear addrs, and that means doing a complete
563 LDT simulation.
564
565 Calls to modify_ldt are intercepted. For each thread, we maintain
566 an LDT (with the same normally-never-allocated optimisation that
567 the kernel does). This is updated as expected via calls to
568 modify_ldt.
569
570 When a thread does an amode calculation involving a segment
571 override prefix, the relevant LDT entry for the thread is
572 consulted. It all works.
573
574 There is a conceptual problem, which appears when switching back to
575 native execution, either temporarily to pass syscalls to the
576 kernel, or permanently, when debugging V. Problem at such points
577 is that it's pretty pointless to copy the simulated machine's
578 segment registers to the real machine, because we'd also need to
579 copy the simulated LDT into the real one, and that's prohibitively
580 expensive.
581
582 Fortunately it looks like no syscalls rely on the segment regs or
583 LDT being correct, so we can get away with it. Apart from that the
584 simulation is pretty straightforward. All 6 segment registers are
585 tracked, although only %ds, %es, %fs and %gs are allowed as
586 prefixes. Perhaps it could be restricted even more than that -- I
587 am not sure what is and isn't allowed in user-mode.
588*/
589
590/* Translate a struct modify_ldt_ldt_s to a VexGuestX86SegDescr, using
591 the Linux kernel's logic (cut-n-paste of code in
592 linux/kernel/ldt.c). */
593
594static
595void translate_to_hw_format ( /* IN */ vki_modify_ldt_t* inn,
sewardja8d8e232005-06-07 20:04:56 +0000596 /* OUT */ VexGuestX86SegDescr* out,
njn2335d112005-05-15 20:52:04 +0000597 Int oldmode )
598{
599 UInt entry_1, entry_2;
600 vg_assert(8 == sizeof(VexGuestX86SegDescr));
601
602 if (0)
603 VG_(printf)("translate_to_hw_format: base %p, limit %d\n",
604 inn->base_addr, inn->limit );
605
606 /* Allow LDTs to be cleared by the user. */
607 if (inn->base_addr == 0 && inn->limit == 0) {
608 if (oldmode ||
609 (inn->contents == 0 &&
610 inn->read_exec_only == 1 &&
611 inn->seg_32bit == 0 &&
612 inn->limit_in_pages == 0 &&
613 inn->seg_not_present == 1 &&
614 inn->useable == 0 )) {
615 entry_1 = 0;
616 entry_2 = 0;
617 goto install;
618 }
619 }
620
621 entry_1 = ((inn->base_addr & 0x0000ffff) << 16) |
622 (inn->limit & 0x0ffff);
623 entry_2 = (inn->base_addr & 0xff000000) |
624 ((inn->base_addr & 0x00ff0000) >> 16) |
625 (inn->limit & 0xf0000) |
626 ((inn->read_exec_only ^ 1) << 9) |
627 (inn->contents << 10) |
628 ((inn->seg_not_present ^ 1) << 15) |
629 (inn->seg_32bit << 22) |
630 (inn->limit_in_pages << 23) |
631 0x7000;
632 if (!oldmode)
633 entry_2 |= (inn->useable << 20);
634
635 /* Install the new entry ... */
636 install:
637 out->LdtEnt.Words.word1 = entry_1;
638 out->LdtEnt.Words.word2 = entry_2;
639}
640
641/* Create a zeroed-out GDT. */
642static VexGuestX86SegDescr* alloc_zeroed_x86_GDT ( void )
643{
644 Int nbytes = VEX_GUEST_X86_GDT_NENT * sizeof(VexGuestX86SegDescr);
645 return VG_(arena_calloc)(VG_AR_CORE, nbytes, 1);
646}
647
648/* Create a zeroed-out LDT. */
649static VexGuestX86SegDescr* alloc_zeroed_x86_LDT ( void )
650{
651 Int nbytes = VEX_GUEST_X86_LDT_NENT * sizeof(VexGuestX86SegDescr);
652 return VG_(arena_calloc)(VG_AR_CORE, nbytes, 1);
653}
654
655/* Free up an LDT or GDT allocated by the above fns. */
656static void free_LDT_or_GDT ( VexGuestX86SegDescr* dt )
657{
658 vg_assert(dt);
659 VG_(arena_free)(VG_AR_CORE, (void*)dt);
660}
661
662/* Copy contents between two existing LDTs. */
663static void copy_LDT_from_to ( VexGuestX86SegDescr* src,
664 VexGuestX86SegDescr* dst )
665{
sewardja8d8e232005-06-07 20:04:56 +0000666 Int i;
667 vg_assert(src);
668 vg_assert(dst);
669 for (i = 0; i < VEX_GUEST_X86_LDT_NENT; i++)
670 dst[i] = src[i];
njn2335d112005-05-15 20:52:04 +0000671}
672
sewardj468dc792005-05-31 10:12:06 +0000673/* Copy contents between two existing GDTs. */
674static void copy_GDT_from_to ( VexGuestX86SegDescr* src,
675 VexGuestX86SegDescr* dst )
676{
sewardja8d8e232005-06-07 20:04:56 +0000677 Int i;
678 vg_assert(src);
679 vg_assert(dst);
680 for (i = 0; i < VEX_GUEST_X86_GDT_NENT; i++)
681 dst[i] = src[i];
sewardj468dc792005-05-31 10:12:06 +0000682}
683
njn2335d112005-05-15 20:52:04 +0000684/* Free this thread's DTs, if it has any. */
685static void deallocate_LGDTs_for_thread ( VexGuestX86State* vex )
686{
687 vg_assert(sizeof(HWord) == sizeof(void*));
688
689 if (0)
690 VG_(printf)("deallocate_LGDTs_for_thread: "
691 "ldt = 0x%x, gdt = 0x%x\n",
692 vex->guest_LDT, vex->guest_GDT );
693
694 if (vex->guest_LDT != (HWord)NULL) {
695 free_LDT_or_GDT( (VexGuestX86SegDescr*)vex->guest_LDT );
696 vex->guest_LDT = (HWord)NULL;
697 }
698
699 if (vex->guest_GDT != (HWord)NULL) {
700 free_LDT_or_GDT( (VexGuestX86SegDescr*)vex->guest_GDT );
701 vex->guest_GDT = (HWord)NULL;
702 }
703}
704
705
706/*
707 * linux/kernel/ldt.c
708 *
709 * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds
710 * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
711 */
712
713/*
714 * read_ldt() is not really atomic - this is not a problem since
715 * synchronization of reads and writes done to the LDT has to be
716 * assured by user-space anyway. Writes are atomic, to protect
717 * the security checks done on new descriptors.
718 */
719static
sewardja8d8e232005-06-07 20:04:56 +0000720SysRes read_ldt ( ThreadId tid, UChar* ptr, UInt bytecount )
njn2335d112005-05-15 20:52:04 +0000721{
sewardja8d8e232005-06-07 20:04:56 +0000722 SysRes res;
njn2335d112005-05-15 20:52:04 +0000723 UInt i, size;
724 UChar* ldt;
725
726 if (0)
727 VG_(printf)("read_ldt: tid = %d, ptr = %p, bytecount = %d\n",
728 tid, ptr, bytecount );
729
730 vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*));
731 vg_assert(8 == sizeof(VexGuestX86SegDescr));
732
733 ldt = (Char*)(VG_(threads)[tid].arch.vex.guest_LDT);
sewardja8d8e232005-06-07 20:04:56 +0000734 res = VG_(mk_SysRes_Success)( 0 );
njn2335d112005-05-15 20:52:04 +0000735 if (ldt == NULL)
736 /* LDT not allocated, meaning all entries are null */
737 goto out;
738
739 size = VEX_GUEST_X86_LDT_NENT * sizeof(VexGuestX86SegDescr);
740 if (size > bytecount)
741 size = bytecount;
742
sewardja8d8e232005-06-07 20:04:56 +0000743 res = VG_(mk_SysRes_Success)( size );
njn2335d112005-05-15 20:52:04 +0000744 for (i = 0; i < size; i++)
745 ptr[i] = ldt[i];
746
747 out:
sewardja8d8e232005-06-07 20:04:56 +0000748 return res;
njn2335d112005-05-15 20:52:04 +0000749}
750
751
752static
sewardja8d8e232005-06-07 20:04:56 +0000753SysRes write_ldt ( ThreadId tid, void* ptr, UInt bytecount, Int oldmode )
njn2335d112005-05-15 20:52:04 +0000754{
sewardja8d8e232005-06-07 20:04:56 +0000755 SysRes res;
njn2335d112005-05-15 20:52:04 +0000756 VexGuestX86SegDescr* ldt;
757 vki_modify_ldt_t* ldt_info;
758
759 if (0)
760 VG_(printf)("write_ldt: tid = %d, ptr = %p, "
761 "bytecount = %d, oldmode = %d\n",
762 tid, ptr, bytecount, oldmode );
763
764 vg_assert(8 == sizeof(VexGuestX86SegDescr));
765 vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*));
766
767 ldt = (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_LDT;
768 ldt_info = (vki_modify_ldt_t*)ptr;
769
sewardja8d8e232005-06-07 20:04:56 +0000770 res = VG_(mk_SysRes_Error)( VKI_EINVAL );
njn2335d112005-05-15 20:52:04 +0000771 if (bytecount != sizeof(vki_modify_ldt_t))
772 goto out;
773
sewardja8d8e232005-06-07 20:04:56 +0000774 res = VG_(mk_SysRes_Error)( VKI_EINVAL );
njn2335d112005-05-15 20:52:04 +0000775 if (ldt_info->entry_number >= VEX_GUEST_X86_LDT_NENT)
776 goto out;
777 if (ldt_info->contents == 3) {
778 if (oldmode)
779 goto out;
780 if (ldt_info->seg_not_present == 0)
781 goto out;
782 }
783
784 /* If this thread doesn't have an LDT, we'd better allocate it
785 now. */
786 if (ldt == (HWord)NULL) {
787 ldt = alloc_zeroed_x86_LDT();
788 VG_(threads)[tid].arch.vex.guest_LDT = (HWord)ldt;
789 }
790
791 /* Install the new entry ... */
792 translate_to_hw_format ( ldt_info, &ldt[ldt_info->entry_number], oldmode );
sewardja8d8e232005-06-07 20:04:56 +0000793 res = VG_(mk_SysRes_Success)( 0 );
njn2335d112005-05-15 20:52:04 +0000794
795 out:
sewardja8d8e232005-06-07 20:04:56 +0000796 return res;
njn2335d112005-05-15 20:52:04 +0000797}
798
799
sewardja8d8e232005-06-07 20:04:56 +0000800static SysRes sys_modify_ldt ( ThreadId tid,
801 Int func, void* ptr, UInt bytecount )
njn2335d112005-05-15 20:52:04 +0000802{
sewardja8d8e232005-06-07 20:04:56 +0000803 SysRes ret = VG_(mk_SysRes_Error)( VKI_ENOSYS );
njn2335d112005-05-15 20:52:04 +0000804
805 switch (func) {
806 case 0:
807 ret = read_ldt(tid, ptr, bytecount);
808 break;
809 case 1:
810 ret = write_ldt(tid, ptr, bytecount, 1);
811 break;
812 case 2:
813 VG_(unimplemented)("sys_modify_ldt: func == 2");
814 /* god knows what this is about */
815 /* ret = read_default_ldt(ptr, bytecount); */
816 /*UNREACHED*/
817 break;
818 case 0x11:
819 ret = write_ldt(tid, ptr, bytecount, 0);
820 break;
821 }
822 return ret;
823}
824
825
sewardja8d8e232005-06-07 20:04:56 +0000826static SysRes sys_set_thread_area ( ThreadId tid, vki_modify_ldt_t* info )
njn2335d112005-05-15 20:52:04 +0000827{
sewardja8d8e232005-06-07 20:04:56 +0000828 Int idx;
njn2335d112005-05-15 20:52:04 +0000829 VexGuestX86SegDescr* gdt;
830
831 vg_assert(8 == sizeof(VexGuestX86SegDescr));
832 vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*));
833
834 if (info == NULL)
sewardja8d8e232005-06-07 20:04:56 +0000835 return VG_(mk_SysRes_Error)( VKI_EFAULT );
njn2335d112005-05-15 20:52:04 +0000836
837 gdt = (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_GDT;
838
839 /* If the thread doesn't have a GDT, allocate it now. */
840 if (!gdt) {
841 gdt = alloc_zeroed_x86_GDT();
842 VG_(threads)[tid].arch.vex.guest_GDT = (HWord)gdt;
843 }
844
845 idx = info->entry_number;
846
847 if (idx == -1) {
848 /* Find and use the first free entry. */
849 for (idx = 0; idx < VEX_GUEST_X86_GDT_NENT; idx++) {
850 if (gdt[idx].LdtEnt.Words.word1 == 0
851 && gdt[idx].LdtEnt.Words.word2 == 0)
852 break;
853 }
854
855 if (idx == VEX_GUEST_X86_GDT_NENT)
sewardja8d8e232005-06-07 20:04:56 +0000856 return VG_(mk_SysRes_Error)( VKI_ESRCH );
njn2335d112005-05-15 20:52:04 +0000857 } else if (idx < 0 || idx >= VEX_GUEST_X86_GDT_NENT) {
sewardja8d8e232005-06-07 20:04:56 +0000858 return VG_(mk_SysRes_Error)( VKI_EINVAL );
njn2335d112005-05-15 20:52:04 +0000859 }
860
861 translate_to_hw_format(info, &gdt[idx], 0);
862
863 VG_TRACK( pre_mem_write, Vg_CoreSysCall, tid,
864 "set_thread_area(info->entry)",
865 (Addr) & info->entry_number, sizeof(unsigned int) );
866 info->entry_number = idx;
867 VG_TRACK( post_mem_write, Vg_CoreSysCall, tid,
868 (Addr) & info->entry_number, sizeof(unsigned int) );
869
sewardja8d8e232005-06-07 20:04:56 +0000870 return VG_(mk_SysRes_Success)( 0 );
njn2335d112005-05-15 20:52:04 +0000871}
872
873
sewardje6d5e722005-06-10 10:27:55 +0000874static SysRes sys_get_thread_area ( ThreadId tid, vki_modify_ldt_t* info )
875{
876 Int idx;
877 VexGuestX86SegDescr* gdt;
878
879 vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*));
880 vg_assert(8 == sizeof(VexGuestX86SegDescr));
881
882 if (info == NULL)
883 return VG_(mk_SysRes_Error)( VKI_EFAULT );
884
885 idx = info->entry_number;
886
887 if (idx < 0 || idx >= VEX_GUEST_X86_GDT_NENT)
888 return VG_(mk_SysRes_Error)( VKI_EINVAL );
889
890 gdt = (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_GDT;
891
892 /* If the thread doesn't have a GDT, allocate it now. */
893 if (!gdt) {
894 gdt = alloc_zeroed_x86_GDT();
895 VG_(threads)[tid].arch.vex.guest_GDT = (HWord)gdt;
896 }
897
898 info->base_addr = ( gdt[idx].LdtEnt.Bits.BaseHi << 24 ) |
899 ( gdt[idx].LdtEnt.Bits.BaseMid << 16 ) |
900 gdt[idx].LdtEnt.Bits.BaseLow;
901 info->limit = ( gdt[idx].LdtEnt.Bits.LimitHi << 16 ) |
902 gdt[idx].LdtEnt.Bits.LimitLow;
903 info->seg_32bit = gdt[idx].LdtEnt.Bits.Default_Big;
904 info->contents = ( gdt[idx].LdtEnt.Bits.Type >> 2 ) & 0x3;
905 info->read_exec_only = ( gdt[idx].LdtEnt.Bits.Type & 0x1 ) ^ 0x1;
906 info->limit_in_pages = gdt[idx].LdtEnt.Bits.Granularity;
907 info->seg_not_present = gdt[idx].LdtEnt.Bits.Pres ^ 0x1;
908 info->useable = gdt[idx].LdtEnt.Bits.Sys;
909 info->reserved = 0;
910
tom10c4b522005-07-19 22:44:33 +0000911 return VG_(mk_SysRes_Success)( 0 );
sewardje6d5e722005-06-10 10:27:55 +0000912}
njn2335d112005-05-15 20:52:04 +0000913
914/* ---------------------------------------------------------------------
915 More thread stuff
916 ------------------------------------------------------------------ */
917
njnaf839f52005-06-23 03:27:57 +0000918void VG_(cleanup_thread) ( ThreadArchState* arch )
njn2335d112005-05-15 20:52:04 +0000919{
920 /* Release arch-specific resources held by this thread. */
921 /* On x86, we have to dump the LDT and GDT. */
922 deallocate_LGDTs_for_thread( &arch->vex );
923}
924
925
926static void setup_child ( /*OUT*/ ThreadArchState *child,
sewardj468dc792005-05-31 10:12:06 +0000927 /*IN*/ ThreadArchState *parent,
928 Bool inherit_parents_GDT )
njn2335d112005-05-15 20:52:04 +0000929{
930 /* We inherit our parent's guest state. */
931 child->vex = parent->vex;
932 child->vex_shadow = parent->vex_shadow;
sewardj468dc792005-05-31 10:12:06 +0000933
njn2335d112005-05-15 20:52:04 +0000934 /* We inherit our parent's LDT. */
935 if (parent->vex.guest_LDT == (HWord)NULL) {
936 /* We hope this is the common case. */
937 child->vex.guest_LDT = (HWord)NULL;
938 } else {
939 /* No luck .. we have to take a copy of the parent's. */
940 child->vex.guest_LDT = (HWord)alloc_zeroed_x86_LDT();
941 copy_LDT_from_to( (VexGuestX86SegDescr*)parent->vex.guest_LDT,
942 (VexGuestX86SegDescr*)child->vex.guest_LDT );
943 }
944
sewardj468dc792005-05-31 10:12:06 +0000945 /* Either we start with an empty GDT (the usual case) or inherit a
946 copy of our parents' one (Quadrics Elan3 driver -style clone
947 only). */
njn2335d112005-05-15 20:52:04 +0000948 child->vex.guest_GDT = (HWord)NULL;
sewardj468dc792005-05-31 10:12:06 +0000949
950 if (inherit_parents_GDT && parent->vex.guest_GDT != (HWord)NULL) {
951 child->vex.guest_GDT = (HWord)alloc_zeroed_x86_GDT();
952 copy_GDT_from_to( (VexGuestX86SegDescr*)parent->vex.guest_GDT,
953 (VexGuestX86SegDescr*)child->vex.guest_GDT );
954 }
njn2335d112005-05-15 20:52:04 +0000955}
956
sewardja8d8e232005-06-07 20:04:56 +0000957
njn2335d112005-05-15 20:52:04 +0000958/* ---------------------------------------------------------------------
nethercote8ff888f2004-11-17 17:11:45 +0000959 PRE/POST wrappers for x86/Linux-specific syscalls
960 ------------------------------------------------------------------ */
961
sewardja8d8e232005-06-07 20:04:56 +0000962#define PRE(name) DEFN_PRE_TEMPLATE(x86_linux, name)
963#define POST(name) DEFN_POST_TEMPLATE(x86_linux, name)
nethercote8ff888f2004-11-17 17:11:45 +0000964
sewardja8d8e232005-06-07 20:04:56 +0000965/* Add prototypes for the wrappers declared here, so that gcc doesn't
966 harass us for not having prototypes. Really this is a kludge --
967 the right thing to do is to make these wrappers 'static' since they
968 aren't visible outside this file, but that requires even more macro
969 magic. */
970DECL_TEMPLATE(x86_linux, sys_socketcall);
971DECL_TEMPLATE(x86_linux, sys_stat64);
972DECL_TEMPLATE(x86_linux, sys_fstat64);
973DECL_TEMPLATE(x86_linux, sys_lstat64);
974DECL_TEMPLATE(x86_linux, sys_clone);
975DECL_TEMPLATE(x86_linux, old_mmap);
tom9548a162005-09-30 08:07:53 +0000976DECL_TEMPLATE(x86_linux, sys_mmap2);
sewardja8d8e232005-06-07 20:04:56 +0000977DECL_TEMPLATE(x86_linux, sys_sigreturn);
978DECL_TEMPLATE(x86_linux, sys_ipc);
979DECL_TEMPLATE(x86_linux, sys_rt_sigreturn);
980DECL_TEMPLATE(x86_linux, sys_modify_ldt);
sewardjbc22cf72005-06-08 00:02:49 +0000981DECL_TEMPLATE(x86_linux, sys_set_thread_area);
sewardje6d5e722005-06-10 10:27:55 +0000982DECL_TEMPLATE(x86_linux, sys_get_thread_area);
sewardj8c257322005-06-08 01:01:48 +0000983DECL_TEMPLATE(x86_linux, sys_ptrace);
sewardj696c5512005-06-08 23:38:32 +0000984DECL_TEMPLATE(x86_linux, sys_sigaction);
985DECL_TEMPLATE(x86_linux, old_select);
sewardjce5a5662005-10-06 03:19:49 +0000986DECL_TEMPLATE(x86_linux, sys_syscall223);
nethercote8ff888f2004-11-17 17:11:45 +0000987
sewardj696c5512005-06-08 23:38:32 +0000988PRE(old_select)
989{
990 /* struct sel_arg_struct {
991 unsigned long n;
992 fd_set *inp, *outp, *exp;
993 struct timeval *tvp;
994 };
995 */
996 PRE_REG_READ1(long, "old_select", struct sel_arg_struct *, args);
997 PRE_MEM_READ( "old_select(args)", ARG1, 5*sizeof(UWord) );
998 *flags |= SfMayBlock;
999 {
1000 UInt* arg_struct = (UInt*)ARG1;
1001 UInt a1, a2, a3, a4, a5;
1002
1003 a1 = arg_struct[0];
1004 a2 = arg_struct[1];
1005 a3 = arg_struct[2];
1006 a4 = arg_struct[3];
1007 a5 = arg_struct[4];
1008
1009 PRINT("old_select ( %d, %p, %p, %p, %p )", a1,a2,a3,a4,a5);
1010 if (a2 != (Addr)NULL)
1011 PRE_MEM_READ( "old_select(readfds)", a2, a1/8 /* __FD_SETSIZE/8 */ );
1012 if (a3 != (Addr)NULL)
1013 PRE_MEM_READ( "old_select(writefds)", a3, a1/8 /* __FD_SETSIZE/8 */ );
1014 if (a4 != (Addr)NULL)
1015 PRE_MEM_READ( "old_select(exceptfds)", a4, a1/8 /* __FD_SETSIZE/8 */ );
1016 if (a5 != (Addr)NULL)
1017 PRE_MEM_READ( "old_select(timeout)", a5, sizeof(struct vki_timeval) );
1018 }
1019}
nethercote3d5e9102004-11-17 18:22:38 +00001020
sewardja8d8e232005-06-07 20:04:56 +00001021PRE(sys_clone)
nethercote3d5e9102004-11-17 18:22:38 +00001022{
sewardjb5f6f512005-03-10 23:59:00 +00001023 UInt cloneflags;
nethercote3d5e9102004-11-17 18:22:38 +00001024
sewardjb5f6f512005-03-10 23:59:00 +00001025 PRINT("sys_clone ( %x, %p, %p, %p, %p )",ARG1,ARG2,ARG3,ARG4,ARG5);
1026 PRE_REG_READ5(int, "clone",
1027 unsigned long, flags,
1028 void *, child_stack,
1029 int *, parent_tidptr,
1030 vki_modify_ldt_t *, tlsinfo,
1031 int *, child_tidptr);
1032
1033 if (ARG1 & VKI_CLONE_PARENT_SETTID) {
1034 PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
sewardj45f4e7c2005-09-27 19:20:21 +00001035 if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int),
1036 VKI_PROT_WRITE)) {
sewardja8d8e232005-06-07 20:04:56 +00001037 SET_STATUS_Failure( VKI_EFAULT );
sewardjb5f6f512005-03-10 23:59:00 +00001038 return;
1039 }
nethercote3d5e9102004-11-17 18:22:38 +00001040 }
sewardjb5f6f512005-03-10 23:59:00 +00001041 if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
1042 PRE_MEM_WRITE("clone(child_tidptr)", ARG5, sizeof(Int));
sewardj45f4e7c2005-09-27 19:20:21 +00001043 if (!VG_(am_is_valid_for_client)(ARG5, sizeof(Int),
1044 VKI_PROT_WRITE)) {
sewardja8d8e232005-06-07 20:04:56 +00001045 SET_STATUS_Failure( VKI_EFAULT );
sewardjb5f6f512005-03-10 23:59:00 +00001046 return;
1047 }
1048 }
1049 if (ARG1 & VKI_CLONE_SETTLS) {
1050 PRE_MEM_READ("clone(tls_user_desc)", ARG4, sizeof(vki_modify_ldt_t));
sewardj45f4e7c2005-09-27 19:20:21 +00001051 if (!VG_(am_is_valid_for_client)(ARG4, sizeof(vki_modify_ldt_t),
1052 VKI_PROT_READ)) {
sewardja8d8e232005-06-07 20:04:56 +00001053 SET_STATUS_Failure( VKI_EFAULT );
sewardjb5f6f512005-03-10 23:59:00 +00001054 return;
1055 }
1056 }
1057
1058 cloneflags = ARG1;
1059
sewardj7eb7c582005-06-23 01:02:53 +00001060 if (!ML_(client_signal_OK)(ARG1 & VKI_CSIGNAL)) {
sewardja8d8e232005-06-07 20:04:56 +00001061 SET_STATUS_Failure( VKI_EINVAL );
sewardjb5f6f512005-03-10 23:59:00 +00001062 return;
1063 }
1064
sewardj468dc792005-05-31 10:12:06 +00001065 /* Be ultra-paranoid and filter out any clone-variants we don't understand:
1066 - ??? specifies clone flags of 0x100011
1067 - ??? specifies clone flags of 0x1200011.
1068 - NPTL specifies clone flags of 0x7D0F00.
1069 - The Quadrics Elan3 driver specifies clone flags of 0xF00.
1070 Everything else is rejected.
1071 */
sewardj934d2d52005-05-31 13:08:03 +00001072 if (
1073 (cloneflags == 0x100011 || cloneflags == 0x1200011
1074 || cloneflags == 0x7D0F00
sewardja8d8e232005-06-07 20:04:56 +00001075 || cloneflags == 0x790F00
sewardjd15ce0c2005-05-31 21:07:01 +00001076 || cloneflags == 0x3D0F00
sewardj934d2d52005-05-31 13:08:03 +00001077 || cloneflags == 0xF00
1078 || cloneflags == 0xF21)) {
1079 /* OK */
sewardj468dc792005-05-31 10:12:06 +00001080 }
1081 else {
1082 /* Nah. We don't like it. Go away. */
1083 goto reject;
1084 }
1085
sewardjb5f6f512005-03-10 23:59:00 +00001086 /* Only look at the flags we really care about */
sewardja8d8e232005-06-07 20:04:56 +00001087 switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS
1088 | VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
sewardjb5f6f512005-03-10 23:59:00 +00001089 case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
1090 /* thread creation */
sewardja8d8e232005-06-07 20:04:56 +00001091 SET_STATUS_from_SysRes(
1092 do_clone(tid,
1093 ARG1, /* flags */
1094 (Addr)ARG2, /* child ESP */
1095 (Int *)ARG3, /* parent_tidptr */
1096 (Int *)ARG5, /* child_tidptr */
1097 (vki_modify_ldt_t *)ARG4)); /* set_tls */
sewardjb5f6f512005-03-10 23:59:00 +00001098 break;
1099
1100 case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
1101 /* FALLTHROUGH - assume vfork == fork */
1102 cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
1103
1104 case 0: /* plain fork */
sewardja8d8e232005-06-07 20:04:56 +00001105 SET_STATUS_from_SysRes(
1106 do_fork_clone(tid,
sewardje7aa4ae2005-06-09 12:43:42 +00001107 cloneflags, /* flags */
sewardja8d8e232005-06-07 20:04:56 +00001108 (Addr)ARG2, /* child ESP */
1109 (Int *)ARG3, /* parent_tidptr */
1110 (Int *)ARG5)); /* child_tidptr */
sewardjb5f6f512005-03-10 23:59:00 +00001111 break;
1112
1113 default:
sewardj468dc792005-05-31 10:12:06 +00001114 reject:
sewardjb5f6f512005-03-10 23:59:00 +00001115 /* should we just ENOSYS? */
sewardj468dc792005-05-31 10:12:06 +00001116 VG_(message)(Vg_UserMsg, "");
1117 VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%x", ARG1);
1118 VG_(message)(Vg_UserMsg, "");
sewardj468dc792005-05-31 10:12:06 +00001119 VG_(message)(Vg_UserMsg, "The only supported clone() uses are:");
1120 VG_(message)(Vg_UserMsg, " - via a threads library (LinuxThreads or NPTL)");
1121 VG_(message)(Vg_UserMsg, " - via the implementation of fork or vfork");
1122 VG_(message)(Vg_UserMsg, " - for the Quadrics Elan3 user-space driver");
sewardjb5f6f512005-03-10 23:59:00 +00001123 VG_(unimplemented)
sewardj468dc792005-05-31 10:12:06 +00001124 ("Valgrind does not support general clone().");
sewardjb5f6f512005-03-10 23:59:00 +00001125 }
1126
sewardja8d8e232005-06-07 20:04:56 +00001127 if (SUCCESS) {
sewardjb5f6f512005-03-10 23:59:00 +00001128 if (ARG1 & VKI_CLONE_PARENT_SETTID)
1129 POST_MEM_WRITE(ARG3, sizeof(Int));
1130 if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID))
1131 POST_MEM_WRITE(ARG5, sizeof(Int));
1132
1133 /* Thread creation was successful; let the child have the chance
1134 to run */
sewardja8d8e232005-06-07 20:04:56 +00001135 *flags |= SfYieldAfter;
sewardjb5f6f512005-03-10 23:59:00 +00001136 }
1137}
1138
sewardja8d8e232005-06-07 20:04:56 +00001139PRE(sys_sigreturn)
sewardjb5f6f512005-03-10 23:59:00 +00001140{
sewardja8d8e232005-06-07 20:04:56 +00001141 ThreadState* tst;
sewardjb5f6f512005-03-10 23:59:00 +00001142 PRINT("sigreturn ( )");
1143
sewardja8d8e232005-06-07 20:04:56 +00001144 vg_assert(VG_(is_valid_tid)(tid));
1145 vg_assert(tid >= 1 && tid < VG_N_THREADS);
1146 vg_assert(VG_(is_running_thread)(tid));
1147
sewardjb5f6f512005-03-10 23:59:00 +00001148 /* Adjust esp to point to start of frame; skip back up over
1149 sigreturn sequence's "popl %eax" and handler ret addr */
sewardja8d8e232005-06-07 20:04:56 +00001150 tst = VG_(get_ThreadState)(tid);
sewardjb5f6f512005-03-10 23:59:00 +00001151 tst->arch.vex.guest_ESP -= sizeof(Addr)+sizeof(Word);
1152
1153 /* This is only so that the EIP is (might be) useful to report if
1154 something goes wrong in the sigreturn */
sewardj7eb7c582005-06-23 01:02:53 +00001155 ML_(fixup_guest_state_to_restart_syscall)(&tst->arch);
sewardjb5f6f512005-03-10 23:59:00 +00001156
sewardj985fabb2005-04-24 14:18:14 +00001157 VG_(sigframe_destroy)(tid, False);
sewardjb5f6f512005-03-10 23:59:00 +00001158
sewardja8d8e232005-06-07 20:04:56 +00001159 /* For unclear reasons, it appears we need the syscall to return
1160 without changing %EAX. Since %EAX is the return value, and can
1161 denote either success or failure, we must set up so that the
1162 driver logic copies it back unchanged. Also, note %EAX is of
1163 the guest registers written by VG_(sigframe_destroy). */
cerion85665ca2005-06-20 15:51:07 +00001164 SET_STATUS_from_SysRes( VG_(mk_SysRes_x86_linux)( tst->arch.vex.guest_EAX ) );
sewardjb5f6f512005-03-10 23:59:00 +00001165
sewardja8d8e232005-06-07 20:04:56 +00001166 /* Check to see if some any signals arose as a result of this. */
1167 *flags |= SfPollAfter;
nethercote3d5e9102004-11-17 18:22:38 +00001168}
1169
sewardja8d8e232005-06-07 20:04:56 +00001170PRE(sys_rt_sigreturn)
sewardjd571aff2005-03-15 14:47:30 +00001171{
sewardja8d8e232005-06-07 20:04:56 +00001172 ThreadState* tst;
sewardjd571aff2005-03-15 14:47:30 +00001173 PRINT("rt_sigreturn ( )");
1174
sewardja8d8e232005-06-07 20:04:56 +00001175 vg_assert(VG_(is_valid_tid)(tid));
1176 vg_assert(tid >= 1 && tid < VG_N_THREADS);
1177 vg_assert(VG_(is_running_thread)(tid));
1178
sewardjd571aff2005-03-15 14:47:30 +00001179 /* Adjust esp to point to start of frame; skip back up over handler
1180 ret addr */
sewardja8d8e232005-06-07 20:04:56 +00001181 tst = VG_(get_ThreadState)(tid);
sewardjd571aff2005-03-15 14:47:30 +00001182 tst->arch.vex.guest_ESP -= sizeof(Addr);
1183
1184 /* This is only so that the EIP is (might be) useful to report if
1185 something goes wrong in the sigreturn */
sewardj7eb7c582005-06-23 01:02:53 +00001186 ML_(fixup_guest_state_to_restart_syscall)(&tst->arch);
sewardjd571aff2005-03-15 14:47:30 +00001187
sewardj5bcde922005-05-03 22:31:22 +00001188 VG_(sigframe_destroy)(tid, True);
sewardjd571aff2005-03-15 14:47:30 +00001189
sewardja8d8e232005-06-07 20:04:56 +00001190 /* For unclear reasons, it appears we need the syscall to return
1191 without changing %EAX. Since %EAX is the return value, and can
1192 denote either success or failure, we must set up so that the
1193 driver logic copies it back unchanged. Also, note %EAX is of
1194 the guest registers written by VG_(sigframe_destroy). */
cerion85665ca2005-06-20 15:51:07 +00001195 SET_STATUS_from_SysRes( VG_(mk_SysRes_x86_linux)( tst->arch.vex.guest_EAX ) );
sewardjd571aff2005-03-15 14:47:30 +00001196
sewardja8d8e232005-06-07 20:04:56 +00001197 /* Check to see if some any signals arose as a result of this. */
1198 *flags |= SfPollAfter;
sewardjd571aff2005-03-15 14:47:30 +00001199}
1200
sewardja8d8e232005-06-07 20:04:56 +00001201PRE(sys_modify_ldt)
nethercote8ff888f2004-11-17 17:11:45 +00001202{
njn22cfccb2004-11-27 16:10:23 +00001203 PRINT("sys_modify_ldt ( %d, %p, %d )", ARG1,ARG2,ARG3);
nethercote8ff888f2004-11-17 17:11:45 +00001204 PRE_REG_READ3(int, "modify_ldt", int, func, void *, ptr,
1205 unsigned long, bytecount);
1206
njn22cfccb2004-11-27 16:10:23 +00001207 if (ARG1 == 0) {
nethercote8ff888f2004-11-17 17:11:45 +00001208 /* read the LDT into ptr */
njn22cfccb2004-11-27 16:10:23 +00001209 PRE_MEM_WRITE( "modify_ldt(ptr)", ARG2, ARG3 );
nethercote8ff888f2004-11-17 17:11:45 +00001210 }
njn22cfccb2004-11-27 16:10:23 +00001211 if (ARG1 == 1 || ARG1 == 0x11) {
nethercote8ff888f2004-11-17 17:11:45 +00001212 /* write the LDT with the entry pointed at by ptr */
njn22cfccb2004-11-27 16:10:23 +00001213 PRE_MEM_READ( "modify_ldt(ptr)", ARG2, sizeof(vki_modify_ldt_t) );
nethercote8ff888f2004-11-17 17:11:45 +00001214 }
1215 /* "do" the syscall ourselves; the kernel never sees it */
sewardja8d8e232005-06-07 20:04:56 +00001216 SET_STATUS_from_SysRes( sys_modify_ldt( tid, ARG1, (void*)ARG2, ARG3 ) );
nethercote8ff888f2004-11-17 17:11:45 +00001217
sewardja8d8e232005-06-07 20:04:56 +00001218 if (ARG1 == 0 && SUCCESS && RES > 0) {
njn22cfccb2004-11-27 16:10:23 +00001219 POST_MEM_WRITE( ARG2, RES );
nethercote8ff888f2004-11-17 17:11:45 +00001220 }
1221}
1222
sewardjbc22cf72005-06-08 00:02:49 +00001223PRE(sys_set_thread_area)
1224{
1225 PRINT("sys_set_thread_area ( %p )", ARG1);
1226 PRE_REG_READ1(int, "set_thread_area", struct user_desc *, u_info)
1227 PRE_MEM_READ( "set_thread_area(u_info)", ARG1, sizeof(vki_modify_ldt_t) );
1228
1229 /* "do" the syscall ourselves; the kernel never sees it */
1230 SET_STATUS_from_SysRes( sys_set_thread_area( tid, (void *)ARG1 ) );
1231}
1232
sewardje6d5e722005-06-10 10:27:55 +00001233PRE(sys_get_thread_area)
1234{
1235 PRINT("sys_get_thread_area ( %p )", ARG1);
1236 PRE_REG_READ1(int, "get_thread_area", struct user_desc *, u_info)
1237 PRE_MEM_WRITE( "get_thread_area(u_info)", ARG1, sizeof(vki_modify_ldt_t) );
1238
1239 /* "do" the syscall ourselves; the kernel never sees it */
1240 SET_STATUS_from_SysRes( sys_get_thread_area( tid, (void *)ARG1 ) );
1241
1242 if (SUCCESS) {
1243 POST_MEM_WRITE( ARG1, sizeof(vki_modify_ldt_t) );
1244 }
1245}
sewardj8c257322005-06-08 01:01:48 +00001246
1247// Parts of this are x86-specific, but the *PEEK* cases are generic.
1248// XXX: Why is the memory pointed to by ARG3 never checked?
1249PRE(sys_ptrace)
1250{
1251 PRINT("sys_ptrace ( %d, %d, %p, %p )", ARG1,ARG2,ARG3,ARG4);
1252 PRE_REG_READ4(int, "ptrace",
1253 long, request, long, pid, long, addr, long, data);
1254 switch (ARG1) {
1255 case VKI_PTRACE_PEEKTEXT:
1256 case VKI_PTRACE_PEEKDATA:
1257 case VKI_PTRACE_PEEKUSR:
1258 PRE_MEM_WRITE( "ptrace(peek)", ARG4,
1259 sizeof (long));
1260 break;
1261 case VKI_PTRACE_GETREGS:
1262 PRE_MEM_WRITE( "ptrace(getregs)", ARG4,
1263 sizeof (struct vki_user_regs_struct));
1264 break;
1265 case VKI_PTRACE_GETFPREGS:
1266 PRE_MEM_WRITE( "ptrace(getfpregs)", ARG4,
1267 sizeof (struct vki_user_i387_struct));
1268 break;
1269 case VKI_PTRACE_GETFPXREGS:
1270 PRE_MEM_WRITE( "ptrace(getfpxregs)", ARG4,
1271 sizeof(struct vki_user_fxsr_struct) );
1272 break;
1273 case VKI_PTRACE_SETREGS:
1274 PRE_MEM_READ( "ptrace(setregs)", ARG4,
1275 sizeof (struct vki_user_regs_struct));
1276 break;
1277 case VKI_PTRACE_SETFPREGS:
1278 PRE_MEM_READ( "ptrace(setfpregs)", ARG4,
1279 sizeof (struct vki_user_i387_struct));
1280 break;
1281 case VKI_PTRACE_SETFPXREGS:
1282 PRE_MEM_READ( "ptrace(setfpxregs)", ARG4,
1283 sizeof(struct vki_user_fxsr_struct) );
1284 break;
1285 default:
1286 break;
1287 }
1288}
1289
1290POST(sys_ptrace)
1291{
1292 switch (ARG1) {
1293 case VKI_PTRACE_PEEKTEXT:
1294 case VKI_PTRACE_PEEKDATA:
1295 case VKI_PTRACE_PEEKUSR:
1296 POST_MEM_WRITE( ARG4, sizeof (long));
1297 break;
1298 case VKI_PTRACE_GETREGS:
1299 POST_MEM_WRITE( ARG4, sizeof (struct vki_user_regs_struct));
1300 break;
1301 case VKI_PTRACE_GETFPREGS:
1302 POST_MEM_WRITE( ARG4, sizeof (struct vki_user_i387_struct));
1303 break;
1304 case VKI_PTRACE_GETFPXREGS:
1305 POST_MEM_WRITE( ARG4, sizeof(struct vki_user_fxsr_struct) );
1306 break;
1307 default:
1308 break;
1309 }
1310}
njnca0518d2004-11-26 19:34:36 +00001311
njnb249fd72004-11-29 14:24:57 +00001312static Addr deref_Addr ( ThreadId tid, Addr a, Char* s )
1313{
1314 Addr* a_p = (Addr*)a;
1315 PRE_MEM_READ( s, (Addr)a_p, sizeof(Addr) );
1316 return *a_p;
1317}
njnc6168192004-11-29 13:54:10 +00001318
sewardja8d8e232005-06-07 20:04:56 +00001319PRE(sys_ipc)
njnc6168192004-11-29 13:54:10 +00001320{
1321 PRINT("sys_ipc ( %d, %d, %d, %d, %p, %d )", ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
1322 // XXX: this is simplistic -- some args are not used in all circumstances.
1323 PRE_REG_READ6(int, "ipc",
1324 vki_uint, call, int, first, int, second, int, third,
1325 void *, ptr, long, fifth)
1326
1327 switch (ARG1 /* call */) {
1328 case VKI_SEMOP:
sewardj7eb7c582005-06-23 01:02:53 +00001329 ML_(generic_PRE_sys_semop)( tid, ARG2, ARG5, ARG3 );
sewardja8d8e232005-06-07 20:04:56 +00001330 *flags |= SfMayBlock;
njnc6168192004-11-29 13:54:10 +00001331 break;
1332 case VKI_SEMGET:
1333 break;
1334 case VKI_SEMCTL:
1335 {
sewardjb369c5e2005-03-24 17:52:02 +00001336 UWord arg = deref_Addr( tid, ARG5, "semctl(arg)" );
sewardj7eb7c582005-06-23 01:02:53 +00001337 ML_(generic_PRE_sys_semctl)( tid, ARG2, ARG3, ARG4, arg );
njnc6168192004-11-29 13:54:10 +00001338 break;
1339 }
1340 case VKI_SEMTIMEDOP:
sewardj7eb7c582005-06-23 01:02:53 +00001341 ML_(generic_PRE_sys_semtimedop)( tid, ARG2, ARG5, ARG3, ARG6 );
sewardja8d8e232005-06-07 20:04:56 +00001342 *flags |= SfMayBlock;
njnc6168192004-11-29 13:54:10 +00001343 break;
1344 case VKI_MSGSND:
njncd405ea2005-08-31 02:44:31 +00001345 ML_(linux_PRE_sys_msgsnd)( tid, ARG2, ARG5, ARG3, ARG4 );
sewardja8d8e232005-06-07 20:04:56 +00001346 if ((ARG4 & VKI_IPC_NOWAIT) == 0)
1347 *flags |= SfMayBlock;
njnc6168192004-11-29 13:54:10 +00001348 break;
njnc6168192004-11-29 13:54:10 +00001349 case VKI_MSGRCV:
1350 {
sewardjb369c5e2005-03-24 17:52:02 +00001351 Addr msgp;
1352 Word msgtyp;
njnc6168192004-11-29 13:54:10 +00001353
sewardjb369c5e2005-03-24 17:52:02 +00001354 msgp = deref_Addr( tid,
1355 (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgp),
1356 "msgrcv(msgp)" );
1357 msgtyp = deref_Addr( tid,
1358 (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgtyp),
1359 "msgrcv(msgp)" );
njnc6168192004-11-29 13:54:10 +00001360
njncd405ea2005-08-31 02:44:31 +00001361 ML_(linux_PRE_sys_msgrcv)( tid, ARG2, msgp, ARG3, msgtyp, ARG4 );
njnc6168192004-11-29 13:54:10 +00001362
sewardja8d8e232005-06-07 20:04:56 +00001363 if ((ARG4 & VKI_IPC_NOWAIT) == 0)
1364 *flags |= SfMayBlock;
njnc6168192004-11-29 13:54:10 +00001365 break;
1366 }
1367 case VKI_MSGGET:
1368 break;
1369 case VKI_MSGCTL:
njncd405ea2005-08-31 02:44:31 +00001370 ML_(linux_PRE_sys_msgctl)( tid, ARG2, ARG3, ARG5 );
njnc6168192004-11-29 13:54:10 +00001371 break;
njnc6168192004-11-29 13:54:10 +00001372 case VKI_SHMAT:
sewardja8d8e232005-06-07 20:04:56 +00001373 {
1374 UWord w;
sewardjb369c5e2005-03-24 17:52:02 +00001375 PRE_MEM_WRITE( "shmat(raddr)", ARG4, sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001376 w = ML_(generic_PRE_sys_shmat)( tid, ARG2, ARG5, ARG3 );
sewardja8d8e232005-06-07 20:04:56 +00001377 if (w == 0)
1378 SET_STATUS_Failure( VKI_EINVAL );
1379 else
1380 ARG5 = w;
njnc6168192004-11-29 13:54:10 +00001381 break;
sewardja8d8e232005-06-07 20:04:56 +00001382 }
njnc6168192004-11-29 13:54:10 +00001383 case VKI_SHMDT:
sewardj7eb7c582005-06-23 01:02:53 +00001384 if (!ML_(generic_PRE_sys_shmdt)(tid, ARG5))
sewardja8d8e232005-06-07 20:04:56 +00001385 SET_STATUS_Failure( VKI_EINVAL );
njnc6168192004-11-29 13:54:10 +00001386 break;
1387 case VKI_SHMGET:
1388 break;
1389 case VKI_SHMCTL: /* IPCOP_shmctl */
sewardj7eb7c582005-06-23 01:02:53 +00001390 ML_(generic_PRE_sys_shmctl)( tid, ARG2, ARG3, ARG5 );
njnc6168192004-11-29 13:54:10 +00001391 break;
njnc6168192004-11-29 13:54:10 +00001392 default:
1393 VG_(message)(Vg_DebugMsg, "FATAL: unhandled syscall(ipc) %d", ARG1 );
1394 VG_(core_panic)("... bye!\n");
1395 break; /*NOTREACHED*/
1396 }
1397}
1398
1399POST(sys_ipc)
1400{
sewardja8d8e232005-06-07 20:04:56 +00001401 vg_assert(SUCCESS);
njnc6168192004-11-29 13:54:10 +00001402 switch (ARG1 /* call */) {
1403 case VKI_SEMOP:
1404 case VKI_SEMGET:
1405 break;
1406 case VKI_SEMCTL:
1407 {
sewardjb369c5e2005-03-24 17:52:02 +00001408 UWord arg = deref_Addr( tid, ARG5, "semctl(arg)" );
sewardj7eb7c582005-06-23 01:02:53 +00001409 ML_(generic_PRE_sys_semctl)( tid, ARG2, ARG3, ARG4, arg );
njnc6168192004-11-29 13:54:10 +00001410 break;
1411 }
1412 case VKI_SEMTIMEDOP:
1413 case VKI_MSGSND:
1414 break;
1415 case VKI_MSGRCV:
1416 {
sewardjb369c5e2005-03-24 17:52:02 +00001417 Addr msgp;
1418 Word msgtyp;
1419
1420 msgp = deref_Addr( tid,
1421 (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgp),
1422 "msgrcv(msgp)" );
1423 msgtyp = deref_Addr( tid,
1424 (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgtyp),
1425 "msgrcv(msgp)" );
1426
njncd405ea2005-08-31 02:44:31 +00001427 ML_(linux_POST_sys_msgrcv)( tid, RES, ARG2, msgp, ARG3, msgtyp, ARG4 );
njnc6168192004-11-29 13:54:10 +00001428 break;
1429 }
1430 case VKI_MSGGET:
1431 break;
1432 case VKI_MSGCTL:
njncd405ea2005-08-31 02:44:31 +00001433 ML_(linux_POST_sys_msgctl)( tid, RES, ARG2, ARG3, ARG5 );
njnc6168192004-11-29 13:54:10 +00001434 break;
njnc6168192004-11-29 13:54:10 +00001435 case VKI_SHMAT:
1436 {
njnc6168192004-11-29 13:54:10 +00001437 Addr addr;
1438
1439 /* force readability. before the syscall it is
1440 * indeed uninitialized, as can be seen in
1441 * glibc/sysdeps/unix/sysv/linux/shmat.c */
sewardjb369c5e2005-03-24 17:52:02 +00001442 POST_MEM_WRITE( ARG4, sizeof( Addr ) );
njnc6168192004-11-29 13:54:10 +00001443
1444 addr = deref_Addr ( tid, ARG4, "shmat(addr)" );
1445 if ( addr > 0 ) {
sewardj7eb7c582005-06-23 01:02:53 +00001446 ML_(generic_POST_sys_shmat)( tid, addr, ARG2, ARG5, ARG3 );
njnc6168192004-11-29 13:54:10 +00001447 }
1448 break;
1449 }
1450 case VKI_SHMDT:
sewardj7eb7c582005-06-23 01:02:53 +00001451 ML_(generic_POST_sys_shmdt)( tid, RES, ARG5 );
njnc6168192004-11-29 13:54:10 +00001452 break;
njnc6168192004-11-29 13:54:10 +00001453 case VKI_SHMGET:
1454 break;
1455 case VKI_SHMCTL:
sewardj7eb7c582005-06-23 01:02:53 +00001456 ML_(generic_POST_sys_shmctl)( tid, RES, ARG2, ARG3, ARG5 );
njnc6168192004-11-29 13:54:10 +00001457 break;
njnc6168192004-11-29 13:54:10 +00001458 default:
1459 VG_(message)(Vg_DebugMsg,
1460 "FATAL: unhandled syscall(ipc) %d",
1461 ARG1 );
1462 VG_(core_panic)("... bye!\n");
1463 break; /*NOTREACHED*/
1464 }
1465}
1466
sewardja8d8e232005-06-07 20:04:56 +00001467PRE(old_mmap)
sewardjb5f6f512005-03-10 23:59:00 +00001468{
sewardja8d8e232005-06-07 20:04:56 +00001469 /* struct mmap_arg_struct {
1470 unsigned long addr;
1471 unsigned long len;
1472 unsigned long prot;
1473 unsigned long flags;
1474 unsigned long fd;
1475 unsigned long offset;
1476 }; */
1477 UWord a1, a2, a3, a4, a5, a6;
tom9548a162005-09-30 08:07:53 +00001478 SysRes r;
sewardja8d8e232005-06-07 20:04:56 +00001479
sewardje6d5e722005-06-10 10:27:55 +00001480 UWord* args = (UWord*)ARG1;
1481 PRE_REG_READ1(long, "old_mmap", struct mmap_arg_struct *, args);
1482 PRE_MEM_READ( "old_mmap(args)", (Addr)args, 6*sizeof(UWord) );
sewardja8d8e232005-06-07 20:04:56 +00001483
sewardj45f4e7c2005-09-27 19:20:21 +00001484 a1 = args[1-1];
1485 a2 = args[2-1];
1486 a3 = args[3-1];
1487 a4 = args[4-1];
1488 a5 = args[5-1];
1489 a6 = args[6-1];
sewardja8d8e232005-06-07 20:04:56 +00001490
1491 PRINT("old_mmap ( %p, %llu, %d, %d, %d, %d )",
1492 a1, (ULong)a2, a3, a4, a5, a6 );
1493
sewardj274461d2005-10-02 17:01:41 +00001494 r = ML_(generic_PRE_sys_mmap)( tid, a1, a2, a3, a4, a5, (Off64T)a6 );
tom9548a162005-09-30 08:07:53 +00001495 SET_STATUS_from_SysRes(r);
1496}
sewardja8d8e232005-06-07 20:04:56 +00001497
tom9548a162005-09-30 08:07:53 +00001498PRE(sys_mmap2)
1499{
1500 SysRes r;
sewardja8d8e232005-06-07 20:04:56 +00001501
tom9548a162005-09-30 08:07:53 +00001502 // Exactly like old_mmap() except:
1503 // - all 6 args are passed in regs, rather than in a memory-block.
1504 // - the file offset is specified in pagesize units rather than bytes,
1505 // so that it can be used for files bigger than 2^32 bytes.
1506 PRINT("sys_mmap2 ( %p, %llu, %d, %d, %d, %d )",
1507 ARG1, (ULong)ARG2, ARG3, ARG4, ARG5, ARG6 );
1508 PRE_REG_READ6(long, "mmap2",
1509 unsigned long, start, unsigned long, length,
1510 unsigned long, prot, unsigned long, flags,
1511 unsigned long, fd, unsigned long, offset);
sewardja8d8e232005-06-07 20:04:56 +00001512
sewardj274461d2005-10-02 17:01:41 +00001513 r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5,
1514 VKI_PAGE_SIZE * (Off64T)ARG6 );
tom9548a162005-09-30 08:07:53 +00001515 SET_STATUS_from_SysRes(r);
sewardjb5f6f512005-03-10 23:59:00 +00001516}
sewardja8d8e232005-06-07 20:04:56 +00001517
1518// XXX: lstat64/fstat64/stat64 are generic, but not necessarily
1519// applicable to every architecture -- I think only to 32-bit archs.
1520// We're going to need something like linux/core_os32.h for such
1521// things, eventually, I think. --njn
1522PRE(sys_lstat64)
njnc6168192004-11-29 13:54:10 +00001523{
sewardja8d8e232005-06-07 20:04:56 +00001524 PRINT("sys_lstat64 ( %p(%s), %p )",ARG1,ARG1,ARG2);
1525 PRE_REG_READ2(long, "lstat64", char *, file_name, struct stat64 *, buf);
1526 PRE_MEM_RASCIIZ( "lstat64(file_name)", ARG1 );
1527 PRE_MEM_WRITE( "lstat64(buf)", ARG2, sizeof(struct vki_stat64) );
1528}
sewardjb5f6f512005-03-10 23:59:00 +00001529
sewardja8d8e232005-06-07 20:04:56 +00001530POST(sys_lstat64)
1531{
1532 vg_assert(SUCCESS);
1533 if (RES == 0) {
1534 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
sewardjb5f6f512005-03-10 23:59:00 +00001535 }
njnc6168192004-11-29 13:54:10 +00001536}
1537
sewardja8d8e232005-06-07 20:04:56 +00001538PRE(sys_stat64)
njnc6168192004-11-29 13:54:10 +00001539{
sewardja8d8e232005-06-07 20:04:56 +00001540 PRINT("sys_stat64 ( %p, %p )",ARG1,ARG2);
1541 PRE_REG_READ2(long, "stat64", char *, file_name, struct stat64 *, buf);
1542 PRE_MEM_RASCIIZ( "stat64(file_name)", ARG1 );
1543 PRE_MEM_WRITE( "stat64(buf)", ARG2, sizeof(struct vki_stat64) );
njnc6168192004-11-29 13:54:10 +00001544}
1545
sewardja8d8e232005-06-07 20:04:56 +00001546POST(sys_stat64)
1547{
1548 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
1549}
1550
1551PRE(sys_fstat64)
1552{
1553 PRINT("sys_fstat64 ( %d, %p )",ARG1,ARG2);
1554 PRE_REG_READ2(long, "fstat64", unsigned long, fd, struct stat64 *, buf);
1555 PRE_MEM_WRITE( "fstat64(buf)", ARG2, sizeof(struct vki_stat64) );
1556}
1557
1558POST(sys_fstat64)
1559{
1560 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
1561}
1562
1563PRE(sys_socketcall)
1564{
1565# define ARG2_0 (((UWord*)ARG2)[0])
1566# define ARG2_1 (((UWord*)ARG2)[1])
1567# define ARG2_2 (((UWord*)ARG2)[2])
1568# define ARG2_3 (((UWord*)ARG2)[3])
1569# define ARG2_4 (((UWord*)ARG2)[4])
1570# define ARG2_5 (((UWord*)ARG2)[5])
1571
1572 *flags |= SfMayBlock;
1573 PRINT("sys_socketcall ( %d, %p )",ARG1,ARG2);
1574 PRE_REG_READ2(long, "socketcall", int, call, unsigned long *, args);
1575
1576 switch (ARG1 /* request */) {
1577
1578 case VKI_SYS_SOCKETPAIR:
1579 /* int socketpair(int d, int type, int protocol, int sv[2]); */
1580 PRE_MEM_READ( "socketcall.socketpair(args)", ARG2, 4*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001581 ML_(generic_PRE_sys_socketpair)( tid, ARG2_0, ARG2_1, ARG2_2, ARG2_3 );
sewardja8d8e232005-06-07 20:04:56 +00001582 break;
1583
1584 case VKI_SYS_SOCKET:
1585 /* int socket(int domain, int type, int protocol); */
1586 PRE_MEM_READ( "socketcall.socket(args)", ARG2, 3*sizeof(Addr) );
1587 break;
1588
1589 case VKI_SYS_BIND:
1590 /* int bind(int sockfd, struct sockaddr *my_addr,
1591 int addrlen); */
1592 PRE_MEM_READ( "socketcall.bind(args)", ARG2, 3*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001593 ML_(generic_PRE_sys_bind)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001594 break;
1595
1596 case VKI_SYS_LISTEN:
1597 /* int listen(int s, int backlog); */
1598 PRE_MEM_READ( "socketcall.listen(args)", ARG2, 2*sizeof(Addr) );
1599 break;
1600
1601 case VKI_SYS_ACCEPT: {
1602 /* int accept(int s, struct sockaddr *addr, int *addrlen); */
1603 PRE_MEM_READ( "socketcall.accept(args)", ARG2, 3*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001604 ML_(generic_PRE_sys_accept)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001605 break;
1606 }
1607
1608 case VKI_SYS_SENDTO:
1609 /* int sendto(int s, const void *msg, int len,
1610 unsigned int flags,
1611 const struct sockaddr *to, int tolen); */
1612 PRE_MEM_READ( "socketcall.sendto(args)", ARG2, 6*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001613 ML_(generic_PRE_sys_sendto)( tid, ARG2_0, ARG2_1, ARG2_2,
sewardja8d8e232005-06-07 20:04:56 +00001614 ARG2_3, ARG2_4, ARG2_5 );
1615 break;
1616
1617 case VKI_SYS_SEND:
1618 /* int send(int s, const void *msg, size_t len, int flags); */
1619 PRE_MEM_READ( "socketcall.send(args)", ARG2, 4*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001620 ML_(generic_PRE_sys_send)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001621 break;
1622
1623 case VKI_SYS_RECVFROM:
1624 /* int recvfrom(int s, void *buf, int len, unsigned int flags,
1625 struct sockaddr *from, int *fromlen); */
1626 PRE_MEM_READ( "socketcall.recvfrom(args)", ARG2, 6*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001627 ML_(generic_PRE_sys_recvfrom)( tid, ARG2_0, ARG2_1, ARG2_2,
sewardja8d8e232005-06-07 20:04:56 +00001628 ARG2_3, ARG2_4, ARG2_5 );
1629 break;
1630
1631 case VKI_SYS_RECV:
1632 /* int recv(int s, void *buf, int len, unsigned int flags); */
1633 /* man 2 recv says:
1634 The recv call is normally used only on a connected socket
1635 (see connect(2)) and is identical to recvfrom with a NULL
1636 from parameter.
1637 */
1638 PRE_MEM_READ( "socketcall.recv(args)", ARG2, 4*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001639 ML_(generic_PRE_sys_recv)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001640 break;
1641
1642 case VKI_SYS_CONNECT:
1643 /* int connect(int sockfd,
1644 struct sockaddr *serv_addr, int addrlen ); */
1645 PRE_MEM_READ( "socketcall.connect(args)", ARG2, 3*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001646 ML_(generic_PRE_sys_connect)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001647 break;
1648
1649 case VKI_SYS_SETSOCKOPT:
1650 /* int setsockopt(int s, int level, int optname,
1651 const void *optval, int optlen); */
1652 PRE_MEM_READ( "socketcall.setsockopt(args)", ARG2, 5*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001653 ML_(generic_PRE_sys_setsockopt)( tid, ARG2_0, ARG2_1, ARG2_2,
sewardja8d8e232005-06-07 20:04:56 +00001654 ARG2_3, ARG2_4 );
1655 break;
1656
1657 case VKI_SYS_GETSOCKOPT:
1658 /* int getsockopt(int s, int level, int optname,
1659 void *optval, socklen_t *optlen); */
1660 PRE_MEM_READ( "socketcall.getsockopt(args)", ARG2, 5*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001661 ML_(generic_PRE_sys_getsockopt)( tid, ARG2_0, ARG2_1, ARG2_2,
sewardja8d8e232005-06-07 20:04:56 +00001662 ARG2_3, ARG2_4 );
1663 break;
1664
1665 case VKI_SYS_GETSOCKNAME:
1666 /* int getsockname(int s, struct sockaddr* name, int* namelen) */
1667 PRE_MEM_READ( "socketcall.getsockname(args)", ARG2, 3*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001668 ML_(generic_PRE_sys_getsockname)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001669 break;
1670
1671 case VKI_SYS_GETPEERNAME:
1672 /* int getpeername(int s, struct sockaddr* name, int* namelen) */
1673 PRE_MEM_READ( "socketcall.getpeername(args)", ARG2, 3*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001674 ML_(generic_PRE_sys_getpeername)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001675 break;
1676
1677 case VKI_SYS_SHUTDOWN:
1678 /* int shutdown(int s, int how); */
1679 PRE_MEM_READ( "socketcall.shutdown(args)", ARG2, 2*sizeof(Addr) );
1680 break;
1681
1682 case VKI_SYS_SENDMSG: {
1683 /* int sendmsg(int s, const struct msghdr *msg, int flags); */
1684
1685 /* this causes warnings, and I don't get why. glibc bug?
1686 * (after all it's glibc providing the arguments array)
1687 PRE_MEM_READ( "socketcall.sendmsg(args)", ARG2, 3*sizeof(Addr) );
1688 */
sewardj7eb7c582005-06-23 01:02:53 +00001689 ML_(generic_PRE_sys_sendmsg)( tid, ARG2_0, ARG2_1 );
sewardja8d8e232005-06-07 20:04:56 +00001690 break;
1691 }
1692
1693 case VKI_SYS_RECVMSG: {
1694 /* int recvmsg(int s, struct msghdr *msg, int flags); */
1695
1696 /* this causes warnings, and I don't get why. glibc bug?
1697 * (after all it's glibc providing the arguments array)
1698 PRE_MEM_READ("socketcall.recvmsg(args)", ARG2, 3*sizeof(Addr) );
1699 */
sewardj7eb7c582005-06-23 01:02:53 +00001700 ML_(generic_PRE_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
sewardja8d8e232005-06-07 20:04:56 +00001701 break;
1702 }
1703
1704 default:
1705 VG_(message)(Vg_DebugMsg,"Warning: unhandled socketcall 0x%x",ARG1);
1706 SET_STATUS_Failure( VKI_EINVAL );
1707 break;
1708 }
1709# undef ARG2_0
1710# undef ARG2_1
1711# undef ARG2_2
1712# undef ARG2_3
1713# undef ARG2_4
1714# undef ARG2_5
1715}
1716
1717POST(sys_socketcall)
1718{
1719# define ARG2_0 (((UWord*)ARG2)[0])
1720# define ARG2_1 (((UWord*)ARG2)[1])
1721# define ARG2_2 (((UWord*)ARG2)[2])
1722# define ARG2_3 (((UWord*)ARG2)[3])
1723# define ARG2_4 (((UWord*)ARG2)[4])
1724# define ARG2_5 (((UWord*)ARG2)[5])
1725
1726 SysRes r;
1727 vg_assert(SUCCESS);
1728 switch (ARG1 /* request */) {
1729
1730 case VKI_SYS_SOCKETPAIR:
sewardj7eb7c582005-06-23 01:02:53 +00001731 r = ML_(generic_POST_sys_socketpair)(
sewardja8d8e232005-06-07 20:04:56 +00001732 tid, VG_(mk_SysRes_Success)(RES),
1733 ARG2_0, ARG2_1, ARG2_2, ARG2_3
1734 );
1735 SET_STATUS_from_SysRes(r);
1736 break;
1737
1738 case VKI_SYS_SOCKET:
sewardj7eb7c582005-06-23 01:02:53 +00001739 r = ML_(generic_POST_sys_socket)( tid, VG_(mk_SysRes_Success)(RES) );
sewardja8d8e232005-06-07 20:04:56 +00001740 SET_STATUS_from_SysRes(r);
1741 break;
1742
1743 case VKI_SYS_BIND:
1744 /* int bind(int sockfd, struct sockaddr *my_addr,
1745 int addrlen); */
1746 break;
1747
1748 case VKI_SYS_LISTEN:
1749 /* int listen(int s, int backlog); */
1750 break;
1751
1752 case VKI_SYS_ACCEPT:
1753 /* int accept(int s, struct sockaddr *addr, int *addrlen); */
sewardj7eb7c582005-06-23 01:02:53 +00001754 r = ML_(generic_POST_sys_accept)( tid, VG_(mk_SysRes_Success)(RES),
sewardja8d8e232005-06-07 20:04:56 +00001755 ARG2_0, ARG2_1, ARG2_2 );
1756 SET_STATUS_from_SysRes(r);
1757 break;
1758
1759 case VKI_SYS_SENDTO:
1760 break;
1761
1762 case VKI_SYS_SEND:
1763 break;
1764
1765 case VKI_SYS_RECVFROM:
sewardj7eb7c582005-06-23 01:02:53 +00001766 ML_(generic_POST_sys_recvfrom)( tid, VG_(mk_SysRes_Success)(RES),
sewardja8d8e232005-06-07 20:04:56 +00001767 ARG2_0, ARG2_1, ARG2_2,
1768 ARG2_3, ARG2_4, ARG2_5 );
1769 break;
1770
1771 case VKI_SYS_RECV:
sewardj7eb7c582005-06-23 01:02:53 +00001772 ML_(generic_POST_sys_recv)( tid, RES, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001773 break;
1774
1775 case VKI_SYS_CONNECT:
1776 break;
1777
1778 case VKI_SYS_SETSOCKOPT:
1779 break;
1780
1781 case VKI_SYS_GETSOCKOPT:
sewardj7eb7c582005-06-23 01:02:53 +00001782 ML_(generic_POST_sys_getsockopt)( tid, VG_(mk_SysRes_Success)(RES),
sewardja8d8e232005-06-07 20:04:56 +00001783 ARG2_0, ARG2_1,
1784 ARG2_2, ARG2_3, ARG2_4 );
1785 break;
1786
1787 case VKI_SYS_GETSOCKNAME:
sewardj7eb7c582005-06-23 01:02:53 +00001788 ML_(generic_POST_sys_getsockname)( tid, VG_(mk_SysRes_Success)(RES),
sewardja8d8e232005-06-07 20:04:56 +00001789 ARG2_0, ARG2_1, ARG2_2 );
1790 break;
1791
1792 case VKI_SYS_GETPEERNAME:
sewardj7eb7c582005-06-23 01:02:53 +00001793 ML_(generic_POST_sys_getpeername)( tid, VG_(mk_SysRes_Success)(RES),
sewardja8d8e232005-06-07 20:04:56 +00001794 ARG2_0, ARG2_1, ARG2_2 );
1795 break;
1796
1797 case VKI_SYS_SHUTDOWN:
1798 break;
1799
1800 case VKI_SYS_SENDMSG:
1801 break;
1802
1803 case VKI_SYS_RECVMSG:
sewardj7eb7c582005-06-23 01:02:53 +00001804 ML_(generic_POST_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
sewardja8d8e232005-06-07 20:04:56 +00001805 break;
1806
1807 default:
1808 VG_(message)(Vg_DebugMsg,"FATAL: unhandled socketcall 0x%x",ARG1);
1809 VG_(core_panic)("... bye!\n");
1810 break; /*NOTREACHED*/
1811 }
1812# undef ARG2_0
1813# undef ARG2_1
1814# undef ARG2_2
1815# undef ARG2_3
1816# undef ARG2_4
1817# undef ARG2_5
1818}
1819
sewardj696c5512005-06-08 23:38:32 +00001820/* Convert from non-RT to RT sigset_t's */
1821static
1822void convert_sigset_to_rt(const vki_old_sigset_t *oldset, vki_sigset_t *set)
1823{
1824 VG_(sigemptyset)(set);
1825 set->sig[0] = *oldset;
1826}
1827PRE(sys_sigaction)
1828{
1829 struct vki_sigaction new, old;
1830 struct vki_sigaction *newp, *oldp;
1831
1832 PRINT("sys_sigaction ( %d, %p, %p )", ARG1,ARG2,ARG3);
1833 PRE_REG_READ3(int, "sigaction",
1834 int, signum, const struct old_sigaction *, act,
1835 struct old_sigaction *, oldact);
1836
1837 newp = oldp = NULL;
1838
tomd9cac2f2005-08-07 15:16:59 +00001839 if (ARG2 != 0) {
1840 struct vki_old_sigaction *sa = (struct vki_old_sigaction *)ARG2;
tom9b52a342005-08-08 16:50:16 +00001841 PRE_MEM_READ( "sigaction(act->sa_handler)", (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler));
1842 PRE_MEM_READ( "sigaction(act->sa_mask)", (Addr)&sa->sa_mask, sizeof(sa->sa_mask));
1843 PRE_MEM_READ( "sigaction(act->sa_flags)", (Addr)&sa->sa_flags, sizeof(sa->sa_flags));
sewardj45f4e7c2005-09-27 19:20:21 +00001844 if (ML_(safe_to_deref)(sa,sizeof(sa))
1845 && (sa->sa_flags & VKI_SA_RESTORER))
tom9b52a342005-08-08 16:50:16 +00001846 PRE_MEM_READ( "sigaction(act->sa_restorer)", (Addr)&sa->sa_restorer, sizeof(sa->sa_restorer));
tomd9cac2f2005-08-07 15:16:59 +00001847 }
sewardj696c5512005-06-08 23:38:32 +00001848
1849 if (ARG3 != 0) {
1850 PRE_MEM_WRITE( "sigaction(oldact)", ARG3, sizeof(struct vki_old_sigaction));
1851 oldp = &old;
1852 }
1853
1854 //jrs 20050207: what?! how can this make any sense?
1855 //if (VG_(is_kerror)(SYSRES))
1856 // return;
1857
1858 if (ARG2 != 0) {
1859 struct vki_old_sigaction *oldnew = (struct vki_old_sigaction *)ARG2;
1860
1861 new.ksa_handler = oldnew->ksa_handler;
1862 new.sa_flags = oldnew->sa_flags;
1863 new.sa_restorer = oldnew->sa_restorer;
1864 convert_sigset_to_rt(&oldnew->sa_mask, &new.sa_mask);
1865 newp = &new;
1866 }
1867
1868 SET_STATUS_from_SysRes( VG_(do_sys_sigaction)(ARG1, newp, oldp) );
1869
1870 if (ARG3 != 0 && SUCCESS && RES == 0) {
1871 struct vki_old_sigaction *oldold = (struct vki_old_sigaction *)ARG3;
1872
1873 oldold->ksa_handler = oldp->ksa_handler;
1874 oldold->sa_flags = oldp->sa_flags;
1875 oldold->sa_restorer = oldp->sa_restorer;
1876 oldold->sa_mask = oldp->sa_mask.sig[0];
1877 }
1878}
1879
1880POST(sys_sigaction)
1881{
1882 vg_assert(SUCCESS);
1883 if (RES == 0 && ARG3 != 0)
1884 POST_MEM_WRITE( ARG3, sizeof(struct vki_old_sigaction));
1885}
1886
sewardjce5a5662005-10-06 03:19:49 +00001887
1888/* ---------------------------------------------------------------
1889 PRE/POST wrappers for x86/Linux-variant specific syscalls
1890 ------------------------------------------------------------ */
1891
1892PRE(sys_syscall223)
1893{
1894 Int err;
1895
1896 /* 223 is used by sys_bproc. If we're not on a declared bproc
1897 variant, fail in the usual way. */
1898
1899 if (!VG_(strstr)(VG_(clo_kernel_variant), "bproc")) {
1900 PRINT("non-existent syscall! (syscall 223)");
1901 PRE_REG_READ0(long, "ni_syscall(223)");
1902 SET_STATUS_Failure( VKI_ENOSYS );
1903 return;
1904 }
1905
1906 err = ML_(linux_variant_PRE_sys_bproc)( ARG1, ARG2, ARG3,
1907 ARG4, ARG5, ARG6 );
1908 if (err) {
1909 SET_STATUS_Failure( err );
1910 return;
1911 }
1912 /* Let it go through. */
1913 *flags |= SfMayBlock; /* who knows? play safe. */
1914}
1915
1916POST(sys_syscall223)
1917{
1918 ML_(linux_variant_POST_sys_bproc)( ARG1, ARG2, ARG3,
1919 ARG4, ARG5, ARG6 );
1920}
1921
sewardj696c5512005-06-08 23:38:32 +00001922#undef PRE
1923#undef POST
1924
nethercote8ff888f2004-11-17 17:11:45 +00001925
1926/* ---------------------------------------------------------------------
1927 The x86/Linux syscall table
1928 ------------------------------------------------------------------ */
1929
sewardje7aa4ae2005-06-09 12:43:42 +00001930/* Add an x86-linux specific wrapper to a syscall table. */
sewardja8d8e232005-06-07 20:04:56 +00001931#define PLAX_(sysno, name) WRAPPER_ENTRY_X_(x86_linux, sysno, name)
1932#define PLAXY(sysno, name) WRAPPER_ENTRY_XY(x86_linux, sysno, name)
1933
nethercote8ff888f2004-11-17 17:11:45 +00001934
nethercote3d5e9102004-11-17 18:22:38 +00001935// This table maps from __NR_xxx syscall numbers (from
1936// linux/include/asm-i386/unistd.h) to the appropriate PRE/POST sys_foo()
1937// wrappers on x86 (as per sys_call_table in linux/arch/i386/kernel/entry.S).
1938//
1939// For those syscalls not handled by Valgrind, the annotation indicate its
1940// arch/OS combination, eg. */* (generic), */Linux (Linux only), ?/?
1941// (unknown).
1942
njnaf839f52005-06-23 03:27:57 +00001943const SyscallTableEntry ML_(syscall_table)[] = {
sewardja8d8e232005-06-07 20:04:56 +00001944//zz // (restart_syscall) // 0
nethercote8ff888f2004-11-17 17:11:45 +00001945 GENX_(__NR_exit, sys_exit), // 1
sewardjb5f6f512005-03-10 23:59:00 +00001946 GENX_(__NR_fork, sys_fork), // 2
nethercote8ff888f2004-11-17 17:11:45 +00001947 GENXY(__NR_read, sys_read), // 3
1948 GENX_(__NR_write, sys_write), // 4
1949
1950 GENXY(__NR_open, sys_open), // 5
1951 GENXY(__NR_close, sys_close), // 6
1952 GENXY(__NR_waitpid, sys_waitpid), // 7
1953 GENXY(__NR_creat, sys_creat), // 8
1954 GENX_(__NR_link, sys_link), // 9
1955
1956 GENX_(__NR_unlink, sys_unlink), // 10
nethercote3d5e9102004-11-17 18:22:38 +00001957 GENX_(__NR_execve, sys_execve), // 11
nethercote8ff888f2004-11-17 17:11:45 +00001958 GENX_(__NR_chdir, sys_chdir), // 12
1959 GENXY(__NR_time, sys_time), // 13
1960 GENX_(__NR_mknod, sys_mknod), // 14
1961
1962 GENX_(__NR_chmod, sys_chmod), // 15
njnefc957c2005-08-26 04:36:10 +00001963//zz LINX_(__NR_lchown, sys_lchown16), // 16
nethercote3d5e9102004-11-17 18:22:38 +00001964 GENX_(__NR_break, sys_ni_syscall), // 17
sewardja8d8e232005-06-07 20:04:56 +00001965//zz // (__NR_oldstat, sys_stat), // 18 (obsolete)
njncd405ea2005-08-31 02:44:31 +00001966 LINX_(__NR_lseek, sys_lseek), // 19
nethercote8ff888f2004-11-17 17:11:45 +00001967
1968 GENX_(__NR_getpid, sys_getpid), // 20
1969 LINX_(__NR_mount, sys_mount), // 21
1970 LINX_(__NR_umount, sys_oldumount), // 22
njna3b67b72005-08-26 04:27:54 +00001971 LINX_(__NR_setuid, sys_setuid16), // 23 ## P
1972 LINX_(__NR_getuid, sys_getuid16), // 24 ## P
sewardja8d8e232005-06-07 20:04:56 +00001973//zz
1974//zz // (__NR_stime, sys_stime), // 25 * (SVr4,SVID,X/OPEN)
sewardj8c257322005-06-08 01:01:48 +00001975 PLAXY(__NR_ptrace, sys_ptrace), // 26
nethercote3d5e9102004-11-17 18:22:38 +00001976 GENX_(__NR_alarm, sys_alarm), // 27
sewardja8d8e232005-06-07 20:04:56 +00001977//zz // (__NR_oldfstat, sys_fstat), // 28 * L -- obsolete
nethercote3d5e9102004-11-17 18:22:38 +00001978 GENX_(__NR_pause, sys_pause), // 29
sewardj8c9ea4e2005-06-08 10:46:56 +00001979
njncd405ea2005-08-31 02:44:31 +00001980 LINX_(__NR_utime, sys_utime), // 30
nethercote3d5e9102004-11-17 18:22:38 +00001981 GENX_(__NR_stty, sys_ni_syscall), // 31
1982 GENX_(__NR_gtty, sys_ni_syscall), // 32
1983 GENX_(__NR_access, sys_access), // 33
sewardj8c9ea4e2005-06-08 10:46:56 +00001984 GENX_(__NR_nice, sys_nice), // 34
1985
nethercote3d5e9102004-11-17 18:22:38 +00001986 GENX_(__NR_ftime, sys_ni_syscall), // 35
sewardj8c9ea4e2005-06-08 10:46:56 +00001987 GENX_(__NR_sync, sys_sync), // 36
njn03f1e582005-03-26 20:08:06 +00001988 GENX_(__NR_kill, sys_kill), // 37
nethercote8ff888f2004-11-17 17:11:45 +00001989 GENX_(__NR_rename, sys_rename), // 38
1990 GENX_(__NR_mkdir, sys_mkdir), // 39
sewardj78b50e42005-06-08 01:47:28 +00001991
1992 GENX_(__NR_rmdir, sys_rmdir), // 40
nethercote8ff888f2004-11-17 17:11:45 +00001993 GENXY(__NR_dup, sys_dup), // 41
njncd405ea2005-08-31 02:44:31 +00001994 LINXY(__NR_pipe, sys_pipe), // 42
sewardj78b50e42005-06-08 01:47:28 +00001995 GENXY(__NR_times, sys_times), // 43
nethercote3d5e9102004-11-17 18:22:38 +00001996 GENX_(__NR_prof, sys_ni_syscall), // 44
sewardja8d8e232005-06-07 20:04:56 +00001997//zz
nethercote3d5e9102004-11-17 18:22:38 +00001998 GENX_(__NR_brk, sys_brk), // 45
njna3b67b72005-08-26 04:27:54 +00001999 LINX_(__NR_setgid, sys_setgid16), // 46
2000 LINX_(__NR_getgid, sys_getgid16), // 47
sewardja8d8e232005-06-07 20:04:56 +00002001//zz // (__NR_signal, sys_signal), // 48 */* (ANSI C)
njna3b67b72005-08-26 04:27:54 +00002002 LINX_(__NR_geteuid, sys_geteuid16), // 49
sewardj696c5512005-06-08 23:38:32 +00002003
njna3b67b72005-08-26 04:27:54 +00002004 LINX_(__NR_getegid, sys_getegid16), // 50
sewardj696c5512005-06-08 23:38:32 +00002005 GENX_(__NR_acct, sys_acct), // 51
2006 LINX_(__NR_umount2, sys_umount), // 52
nethercote3d5e9102004-11-17 18:22:38 +00002007 GENX_(__NR_lock, sys_ni_syscall), // 53
2008 GENXY(__NR_ioctl, sys_ioctl), // 54
sewardj696c5512005-06-08 23:38:32 +00002009
2010 GENXY(__NR_fcntl, sys_fcntl), // 55
nethercote3d5e9102004-11-17 18:22:38 +00002011 GENX_(__NR_mpx, sys_ni_syscall), // 56
sewardj696c5512005-06-08 23:38:32 +00002012 GENX_(__NR_setpgid, sys_setpgid), // 57
nethercote3d5e9102004-11-17 18:22:38 +00002013 GENX_(__NR_ulimit, sys_ni_syscall), // 58
sewardja8d8e232005-06-07 20:04:56 +00002014//zz // (__NR_oldolduname, sys_olduname), // 59 Linux -- obsolete
2015//zz
sewardj78b50e42005-06-08 01:47:28 +00002016 GENX_(__NR_umask, sys_umask), // 60
sewardj696c5512005-06-08 23:38:32 +00002017 GENX_(__NR_chroot, sys_chroot), // 61
sewardja8d8e232005-06-07 20:04:56 +00002018//zz // (__NR_ustat, sys_ustat) // 62 SVr4 -- deprecated
nethercote8ff888f2004-11-17 17:11:45 +00002019 GENXY(__NR_dup2, sys_dup2), // 63
sewardj1d887112005-05-30 21:44:08 +00002020 GENX_(__NR_getppid, sys_getppid), // 64
sewardj78b50e42005-06-08 01:47:28 +00002021
2022 GENX_(__NR_getpgrp, sys_getpgrp), // 65
sewardj696c5512005-06-08 23:38:32 +00002023 GENX_(__NR_setsid, sys_setsid), // 66
2024 PLAXY(__NR_sigaction, sys_sigaction), // 67
sewardja8d8e232005-06-07 20:04:56 +00002025//zz // (__NR_sgetmask, sys_sgetmask), // 68 */* (ANSI C)
2026//zz // (__NR_ssetmask, sys_ssetmask), // 69 */* (ANSI C)
2027//zz
njna3b67b72005-08-26 04:27:54 +00002028 LINX_(__NR_setreuid, sys_setreuid16), // 70
2029 LINX_(__NR_setregid, sys_setregid16), // 71
sewardja8d8e232005-06-07 20:04:56 +00002030//zz GENX_(__NR_sigsuspend, sys_sigsuspend), // 72
njncd405ea2005-08-31 02:44:31 +00002031 LINXY(__NR_sigpending, sys_sigpending), // 73
sewardja8d8e232005-06-07 20:04:56 +00002032//zz // (__NR_sethostname, sys_sethostname), // 74 */*
2033//zz
nethercote3d5e9102004-11-17 18:22:38 +00002034 GENX_(__NR_setrlimit, sys_setrlimit), // 75
sewardj696c5512005-06-08 23:38:32 +00002035 GENXY(__NR_getrlimit, sys_old_getrlimit), // 76
2036 GENXY(__NR_getrusage, sys_getrusage), // 77
nethercote3d5e9102004-11-17 18:22:38 +00002037 GENXY(__NR_gettimeofday, sys_gettimeofday), // 78
sewardj696c5512005-06-08 23:38:32 +00002038 GENX_(__NR_settimeofday, sys_settimeofday), // 79
2039
njna3b67b72005-08-26 04:27:54 +00002040 LINXY(__NR_getgroups, sys_getgroups16), // 80
2041 LINX_(__NR_setgroups, sys_setgroups16), // 81
sewardj696c5512005-06-08 23:38:32 +00002042 PLAX_(__NR_select, old_select), // 82
sewardj78b50e42005-06-08 01:47:28 +00002043 GENX_(__NR_symlink, sys_symlink), // 83
sewardja8d8e232005-06-07 20:04:56 +00002044//zz // (__NR_oldlstat, sys_lstat), // 84 -- obsolete
2045//zz
rjwalsh17d85302004-11-18 22:56:09 +00002046 GENX_(__NR_readlink, sys_readlink), // 85
sewardja8d8e232005-06-07 20:04:56 +00002047//zz // (__NR_uselib, sys_uselib), // 86 */Linux
2048//zz // (__NR_swapon, sys_swapon), // 87 */Linux
2049//zz // (__NR_reboot, sys_reboot), // 88 */Linux
2050//zz // (__NR_readdir, old_readdir), // 89 -- superseded
2051//zz
2052 PLAX_(__NR_mmap, old_mmap), // 90
nethercote8ff888f2004-11-17 17:11:45 +00002053 GENXY(__NR_munmap, sys_munmap), // 91
sewardj696c5512005-06-08 23:38:32 +00002054 GENX_(__NR_truncate, sys_truncate), // 92
sewardj8c257322005-06-08 01:01:48 +00002055 GENX_(__NR_ftruncate, sys_ftruncate), // 93
sewardj696c5512005-06-08 23:38:32 +00002056 GENX_(__NR_fchmod, sys_fchmod), // 94
2057
njnefc957c2005-08-26 04:36:10 +00002058 LINX_(__NR_fchown, sys_fchown16), // 95
sewardj696c5512005-06-08 23:38:32 +00002059 GENX_(__NR_getpriority, sys_getpriority), // 96
2060 GENX_(__NR_setpriority, sys_setpriority), // 97
nethercote3d5e9102004-11-17 18:22:38 +00002061 GENX_(__NR_profil, sys_ni_syscall), // 98
sewardj696c5512005-06-08 23:38:32 +00002062 GENXY(__NR_statfs, sys_statfs), // 99
2063
2064 GENXY(__NR_fstatfs, sys_fstatfs), // 100
2065 LINX_(__NR_ioperm, sys_ioperm), // 101
sewardja8d8e232005-06-07 20:04:56 +00002066 PLAXY(__NR_socketcall, sys_socketcall), // 102 x86/Linux-only
sewardj696c5512005-06-08 23:38:32 +00002067 LINXY(__NR_syslog, sys_syslog), // 103
2068 GENXY(__NR_setitimer, sys_setitimer), // 104
2069
2070 GENXY(__NR_getitimer, sys_getitimer), // 105
2071 GENXY(__NR_stat, sys_newstat), // 106
2072 GENXY(__NR_lstat, sys_newlstat), // 107
2073 GENXY(__NR_fstat, sys_newfstat), // 108
sewardja8d8e232005-06-07 20:04:56 +00002074//zz // (__NR_olduname, sys_uname), // 109 -- obsolete
2075//zz
sewardj696c5512005-06-08 23:38:32 +00002076 GENX_(__NR_iopl, sys_iopl), // 110
2077 LINX_(__NR_vhangup, sys_vhangup), // 111
nethercote3d5e9102004-11-17 18:22:38 +00002078 GENX_(__NR_idle, sys_ni_syscall), // 112
sewardja8d8e232005-06-07 20:04:56 +00002079//zz // (__NR_vm86old, sys_vm86old), // 113 x86/Linux-only
nethercote3d5e9102004-11-17 18:22:38 +00002080 GENXY(__NR_wait4, sys_wait4), // 114
sewardja8d8e232005-06-07 20:04:56 +00002081//zz
2082//zz // (__NR_swapoff, sys_swapoff), // 115 */Linux
sewardj696c5512005-06-08 23:38:32 +00002083 LINXY(__NR_sysinfo, sys_sysinfo), // 116
njnc6168192004-11-29 13:54:10 +00002084 PLAXY(__NR_ipc, sys_ipc), // 117
sewardj78b50e42005-06-08 01:47:28 +00002085 GENX_(__NR_fsync, sys_fsync), // 118
sewardjb5f6f512005-03-10 23:59:00 +00002086 PLAX_(__NR_sigreturn, sys_sigreturn), // 119 ?/Linux
nethercote8ff888f2004-11-17 17:11:45 +00002087
nethercote3d5e9102004-11-17 18:22:38 +00002088 PLAX_(__NR_clone, sys_clone), // 120
sewardja8d8e232005-06-07 20:04:56 +00002089//zz // (__NR_setdomainname, sys_setdomainname), // 121 */*(?)
nethercote3d5e9102004-11-17 18:22:38 +00002090 GENXY(__NR_uname, sys_newuname), // 122
2091 PLAX_(__NR_modify_ldt, sys_modify_ldt), // 123
sewardja8d8e232005-06-07 20:04:56 +00002092//zz LINXY(__NR_adjtimex, sys_adjtimex), // 124
2093//zz
nethercote3d5e9102004-11-17 18:22:38 +00002094 GENXY(__NR_mprotect, sys_mprotect), // 125
njncd405ea2005-08-31 02:44:31 +00002095 LINXY(__NR_sigprocmask, sys_sigprocmask), // 126
sewardja8d8e232005-06-07 20:04:56 +00002096//zz // Nb: create_module() was removed 2.4-->2.6
nethercote3d5e9102004-11-17 18:22:38 +00002097 GENX_(__NR_create_module, sys_ni_syscall), // 127
sewardj696c5512005-06-08 23:38:32 +00002098 GENX_(__NR_init_module, sys_init_module), // 128
sewardja8d8e232005-06-07 20:04:56 +00002099//zz // (__NR_delete_module, sys_delete_module), // 129 (*/Linux)?
2100//zz
2101//zz // Nb: get_kernel_syms() was removed 2.4-->2.6
nethercote3d5e9102004-11-17 18:22:38 +00002102 GENX_(__NR_get_kernel_syms, sys_ni_syscall), // 130
njncd405ea2005-08-31 02:44:31 +00002103 LINX_(__NR_quotactl, sys_quotactl), // 131
sewardj696c5512005-06-08 23:38:32 +00002104 GENX_(__NR_getpgid, sys_getpgid), // 132
2105 GENX_(__NR_fchdir, sys_fchdir), // 133
sewardja8d8e232005-06-07 20:04:56 +00002106//zz // (__NR_bdflush, sys_bdflush), // 134 */Linux
2107//zz
2108//zz // (__NR_sysfs, sys_sysfs), // 135 SVr4
sewardj696c5512005-06-08 23:38:32 +00002109 LINX_(__NR_personality, sys_personality), // 136
nethercote3d5e9102004-11-17 18:22:38 +00002110 GENX_(__NR_afs_syscall, sys_ni_syscall), // 137
sewardj696c5512005-06-08 23:38:32 +00002111 LINX_(__NR_setfsuid, sys_setfsuid16), // 138
2112 LINX_(__NR_setfsgid, sys_setfsgid16), // 139
2113
nethercote8ff888f2004-11-17 17:11:45 +00002114 LINXY(__NR__llseek, sys_llseek), // 140
sewardj78b50e42005-06-08 01:47:28 +00002115 GENXY(__NR_getdents, sys_getdents), // 141
nethercote3d5e9102004-11-17 18:22:38 +00002116 GENX_(__NR__newselect, sys_select), // 142
sewardj696c5512005-06-08 23:38:32 +00002117 GENX_(__NR_flock, sys_flock), // 143
2118 GENX_(__NR_msync, sys_msync), // 144
2119
nethercote3d5e9102004-11-17 18:22:38 +00002120 GENXY(__NR_readv, sys_readv), // 145
2121 GENX_(__NR_writev, sys_writev), // 146
sewardj696c5512005-06-08 23:38:32 +00002122 GENX_(__NR_getsid, sys_getsid), // 147
2123 GENX_(__NR_fdatasync, sys_fdatasync), // 148
nethercote8ff888f2004-11-17 17:11:45 +00002124 LINXY(__NR__sysctl, sys_sysctl), // 149
sewardj696c5512005-06-08 23:38:32 +00002125
2126 GENX_(__NR_mlock, sys_mlock), // 150
2127 GENX_(__NR_munlock, sys_munlock), // 151
2128 GENX_(__NR_mlockall, sys_mlockall), // 152
njncd405ea2005-08-31 02:44:31 +00002129 LINX_(__NR_munlockall, sys_munlockall), // 153
njnb2480c92005-08-30 02:17:23 +00002130 LINXY(__NR_sched_setparam, sys_sched_setparam), // 154
sewardje6d5e722005-06-10 10:27:55 +00002131
njnb2480c92005-08-30 02:17:23 +00002132 LINXY(__NR_sched_getparam, sys_sched_getparam), // 155
2133 LINX_(__NR_sched_setscheduler, sys_sched_setscheduler), // 156
2134 LINX_(__NR_sched_getscheduler, sys_sched_getscheduler), // 157
2135 LINX_(__NR_sched_yield, sys_sched_yield), // 158
2136 LINX_(__NR_sched_get_priority_max, sys_sched_get_priority_max),// 159
sewardj78b50e42005-06-08 01:47:28 +00002137
njnb2480c92005-08-30 02:17:23 +00002138 LINX_(__NR_sched_get_priority_min, sys_sched_get_priority_min),// 160
2139//zz //LINX?(__NR_sched_rr_get_interval, sys_sched_rr_get_interval), // 161 */*
nethercote8ff888f2004-11-17 17:11:45 +00002140 GENXY(__NR_nanosleep, sys_nanosleep), // 162
2141 GENX_(__NR_mremap, sys_mremap), // 163
sewardje6d5e722005-06-10 10:27:55 +00002142 LINX_(__NR_setresuid, sys_setresuid16), // 164
2143
2144 LINXY(__NR_getresuid, sys_getresuid16), // 165
sewardja8d8e232005-06-07 20:04:56 +00002145//zz // (__NR_vm86, sys_vm86), // 166 x86/Linux-only
nethercote3d5e9102004-11-17 18:22:38 +00002146 GENX_(__NR_query_module, sys_ni_syscall), // 167
2147 GENXY(__NR_poll, sys_poll), // 168
sewardja8d8e232005-06-07 20:04:56 +00002148//zz // (__NR_nfsservctl, sys_nfsservctl), // 169 */Linux
2149//zz
sewardje6d5e722005-06-10 10:27:55 +00002150 LINX_(__NR_setresgid, sys_setresgid16), // 170
2151 LINXY(__NR_getresgid, sys_getresgid16), // 171
2152 LINX_(__NR_prctl, sys_prctl), // 172
sewardjd571aff2005-03-15 14:47:30 +00002153 PLAX_(__NR_rt_sigreturn, sys_rt_sigreturn), // 173 x86/Linux only?
njncd405ea2005-08-31 02:44:31 +00002154 LINXY(__NR_rt_sigaction, sys_rt_sigaction), // 174
nethercote8ff888f2004-11-17 17:11:45 +00002155
njncd405ea2005-08-31 02:44:31 +00002156 LINXY(__NR_rt_sigprocmask, sys_rt_sigprocmask), // 175
2157 LINXY(__NR_rt_sigpending, sys_rt_sigpending), // 176
2158 LINXY(__NR_rt_sigtimedwait, sys_rt_sigtimedwait),// 177
2159 LINXY(__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo),// 178
2160 LINX_(__NR_rt_sigsuspend, sys_rt_sigsuspend), // 179
sewardje6d5e722005-06-10 10:27:55 +00002161
2162 GENXY(__NR_pread64, sys_pread64), // 180
2163 GENX_(__NR_pwrite64, sys_pwrite64), // 181
njnefc957c2005-08-26 04:36:10 +00002164 LINX_(__NR_chown, sys_chown16), // 182
nethercote3d5e9102004-11-17 18:22:38 +00002165 GENXY(__NR_getcwd, sys_getcwd), // 183
njn9fe7b122005-08-26 04:03:04 +00002166 LINXY(__NR_capget, sys_capget), // 184
sewardje6d5e722005-06-10 10:27:55 +00002167
njn9fe7b122005-08-26 04:03:04 +00002168 LINX_(__NR_capset, sys_capset), // 185
nethercote3d5e9102004-11-17 18:22:38 +00002169 GENXY(__NR_sigaltstack, sys_sigaltstack), // 186
sewardje6d5e722005-06-10 10:27:55 +00002170 LINXY(__NR_sendfile, sys_sendfile), // 187
2171 GENXY(__NR_getpmsg, sys_getpmsg), // 188
2172 GENX_(__NR_putpmsg, sys_putpmsg), // 189
nethercote8ff888f2004-11-17 17:11:45 +00002173
sewardjc93d7b62005-03-12 20:45:56 +00002174 // Nb: we treat vfork as fork
2175 GENX_(__NR_vfork, sys_fork), // 190
nethercote3d5e9102004-11-17 18:22:38 +00002176 GENXY(__NR_ugetrlimit, sys_getrlimit), // 191
tom9548a162005-09-30 08:07:53 +00002177 PLAX_(__NR_mmap2, sys_mmap2), // 192
sewardje6d5e722005-06-10 10:27:55 +00002178 GENX_(__NR_truncate64, sys_truncate64), // 193
2179 GENX_(__NR_ftruncate64, sys_ftruncate64), // 194
2180
sewardja8d8e232005-06-07 20:04:56 +00002181 PLAXY(__NR_stat64, sys_stat64), // 195
2182 PLAXY(__NR_lstat64, sys_lstat64), // 196
2183 PLAXY(__NR_fstat64, sys_fstat64), // 197
sewardje6d5e722005-06-10 10:27:55 +00002184 GENX_(__NR_lchown32, sys_lchown), // 198
nethercote8ff888f2004-11-17 17:11:45 +00002185 GENX_(__NR_getuid32, sys_getuid), // 199
sewardj78b50e42005-06-08 01:47:28 +00002186
2187 GENX_(__NR_getgid32, sys_getgid), // 200
nethercote8ff888f2004-11-17 17:11:45 +00002188 GENX_(__NR_geteuid32, sys_geteuid), // 201
sewardj78b50e42005-06-08 01:47:28 +00002189 GENX_(__NR_getegid32, sys_getegid), // 202
sewardje6d5e722005-06-10 10:27:55 +00002190 GENX_(__NR_setreuid32, sys_setreuid), // 203
2191 GENX_(__NR_setregid32, sys_setregid), // 204
sewardj78b50e42005-06-08 01:47:28 +00002192
2193 GENXY(__NR_getgroups32, sys_getgroups), // 205
sewardje6d5e722005-06-10 10:27:55 +00002194 GENX_(__NR_setgroups32, sys_setgroups), // 206
2195 GENX_(__NR_fchown32, sys_fchown), // 207
2196 LINX_(__NR_setresuid32, sys_setresuid), // 208
sewardj78b50e42005-06-08 01:47:28 +00002197 LINXY(__NR_getresuid32, sys_getresuid), // 209
2198
sewardje6d5e722005-06-10 10:27:55 +00002199 LINX_(__NR_setresgid32, sys_setresgid), // 210
sewardj78b50e42005-06-08 01:47:28 +00002200 LINXY(__NR_getresgid32, sys_getresgid), // 211
sewardje6d5e722005-06-10 10:27:55 +00002201 GENX_(__NR_chown32, sys_chown), // 212
2202 GENX_(__NR_setuid32, sys_setuid), // 213
2203 GENX_(__NR_setgid32, sys_setgid), // 214
2204
2205 LINX_(__NR_setfsuid32, sys_setfsuid), // 215
2206 LINX_(__NR_setfsgid32, sys_setfsgid), // 216
sewardja8d8e232005-06-07 20:04:56 +00002207//zz // (__NR_pivot_root, sys_pivot_root), // 217 */Linux
sewardje6d5e722005-06-10 10:27:55 +00002208 GENXY(__NR_mincore, sys_mincore), // 218
nethercote3d5e9102004-11-17 18:22:38 +00002209 GENX_(__NR_madvise, sys_madvise), // 219
nethercote8ff888f2004-11-17 17:11:45 +00002210
nethercote3d5e9102004-11-17 18:22:38 +00002211 GENXY(__NR_getdents64, sys_getdents64), // 220
2212 GENXY(__NR_fcntl64, sys_fcntl64), // 221
2213 GENX_(222, sys_ni_syscall), // 222
sewardjce5a5662005-10-06 03:19:49 +00002214 PLAXY(223, sys_syscall223), // 223 // sys_bproc?
sewardj8c257322005-06-08 01:01:48 +00002215 LINX_(__NR_gettid, sys_gettid), // 224
2216
sewardja8d8e232005-06-07 20:04:56 +00002217//zz // (__NR_readahead, sys_readahead), // 225 */(Linux?)
njn65ccc502005-08-30 01:53:54 +00002218 LINX_(__NR_setxattr, sys_setxattr), // 226
2219 LINX_(__NR_lsetxattr, sys_lsetxattr), // 227
2220 LINX_(__NR_fsetxattr, sys_fsetxattr), // 228
2221 LINXY(__NR_getxattr, sys_getxattr), // 229
sewardje6d5e722005-06-10 10:27:55 +00002222
njn65ccc502005-08-30 01:53:54 +00002223 LINXY(__NR_lgetxattr, sys_lgetxattr), // 230
2224 LINXY(__NR_fgetxattr, sys_fgetxattr), // 231
2225 LINXY(__NR_listxattr, sys_listxattr), // 232
2226 LINXY(__NR_llistxattr, sys_llistxattr), // 233
2227 LINXY(__NR_flistxattr, sys_flistxattr), // 234
sewardje6d5e722005-06-10 10:27:55 +00002228
njn65ccc502005-08-30 01:53:54 +00002229 LINX_(__NR_removexattr, sys_removexattr), // 235
2230 LINX_(__NR_lremovexattr, sys_lremovexattr), // 236
2231 LINX_(__NR_fremovexattr, sys_fremovexattr), // 237
sewardja8d8e232005-06-07 20:04:56 +00002232//zz LINX_(__NR_tkill, sys_tkill), // 238 */Linux
sewardje6d5e722005-06-10 10:27:55 +00002233 LINXY(__NR_sendfile64, sys_sendfile64), // 239
2234
sewardjbc22cf72005-06-08 00:02:49 +00002235 LINXY(__NR_futex, sys_futex), // 240
njnb2480c92005-08-30 02:17:23 +00002236 LINX_(__NR_sched_setaffinity, sys_sched_setaffinity), // 241
2237 LINXY(__NR_sched_getaffinity, sys_sched_getaffinity), // 242
sewardjbc22cf72005-06-08 00:02:49 +00002238 PLAX_(__NR_set_thread_area, sys_set_thread_area), // 243
sewardje6d5e722005-06-10 10:27:55 +00002239 PLAX_(__NR_get_thread_area, sys_get_thread_area), // 244
2240
sewardj45f4e7c2005-09-27 19:20:21 +00002241 LINXY(__NR_io_setup, sys_io_setup), // 245
sewardje6d5e722005-06-10 10:27:55 +00002242 LINX_(__NR_io_destroy, sys_io_destroy), // 246
2243 LINXY(__NR_io_getevents, sys_io_getevents), // 247
2244 LINX_(__NR_io_submit, sys_io_submit), // 248
2245 LINXY(__NR_io_cancel, sys_io_cancel), // 249
2246
tom72440832005-06-15 10:31:10 +00002247 LINX_(__NR_fadvise64, sys_fadvise64), // 250 */(Linux?)
nethercote3d5e9102004-11-17 18:22:38 +00002248 GENX_(251, sys_ni_syscall), // 251
sewardjb5f6f512005-03-10 23:59:00 +00002249 LINX_(__NR_exit_group, sys_exit_group), // 252
sewardje6d5e722005-06-10 10:27:55 +00002250 GENXY(__NR_lookup_dcookie, sys_lookup_dcookie), // 253
2251 LINXY(__NR_epoll_create, sys_epoll_create), // 254
2252
2253 LINX_(__NR_epoll_ctl, sys_epoll_ctl), // 255
2254 LINXY(__NR_epoll_wait, sys_epoll_wait), // 256
sewardja8d8e232005-06-07 20:04:56 +00002255//zz // (__NR_remap_file_pages, sys_remap_file_pages), // 257 */Linux
sewardjbc22cf72005-06-08 00:02:49 +00002256 LINX_(__NR_set_tid_address, sys_set_tid_address), // 258
njn424c0562005-08-26 03:54:30 +00002257 LINXY(__NR_timer_create, sys_timer_create), // 259
sewardje6d5e722005-06-10 10:27:55 +00002258
njn424c0562005-08-26 03:54:30 +00002259 LINXY(__NR_timer_settime, sys_timer_settime), // (timer_create+1)
2260 LINXY(__NR_timer_gettime, sys_timer_gettime), // (timer_create+2)
2261 LINX_(__NR_timer_getoverrun, sys_timer_getoverrun),//(timer_create+3)
2262 LINX_(__NR_timer_delete, sys_timer_delete), // (timer_create+4)
njn1588bc02005-08-26 03:49:43 +00002263 LINX_(__NR_clock_settime, sys_clock_settime), // (timer_create+5)
sewardje6d5e722005-06-10 10:27:55 +00002264
njn1588bc02005-08-26 03:49:43 +00002265 LINXY(__NR_clock_gettime, sys_clock_gettime), // (timer_create+6)
2266 LINXY(__NR_clock_getres, sys_clock_getres), // (timer_create+7)
2267 LINXY(__NR_clock_nanosleep, sys_clock_nanosleep),// (timer_create+8) */*
sewardje6d5e722005-06-10 10:27:55 +00002268 GENXY(__NR_statfs64, sys_statfs64), // 268
2269 GENXY(__NR_fstatfs64, sys_fstatfs64), // 269
2270
sewardjbc22cf72005-06-08 00:02:49 +00002271 LINX_(__NR_tgkill, sys_tgkill), // 270 */Linux
sewardje6d5e722005-06-10 10:27:55 +00002272 GENX_(__NR_utimes, sys_utimes), // 271
tom72440832005-06-15 10:31:10 +00002273 LINX_(__NR_fadvise64_64, sys_fadvise64_64), // 272 */(Linux?)
nethercote3d5e9102004-11-17 18:22:38 +00002274 GENX_(__NR_vserver, sys_ni_syscall), // 273
tom70a5cb02005-10-20 17:00:23 +00002275 LINX_(__NR_mbind, sys_mbind), // 274 ?/?
2276
tom2af58f22005-07-22 15:04:14 +00002277 LINXY(__NR_get_mempolicy, sys_get_mempolicy), // 275 ?/?
2278 LINX_(__NR_set_mempolicy, sys_set_mempolicy), // 276 ?/?
njn4279a882005-08-26 03:43:28 +00002279 LINXY(__NR_mq_open, sys_mq_open), // 277
2280 LINX_(__NR_mq_unlink, sys_mq_unlink), // (mq_open+1)
2281 LINX_(__NR_mq_timedsend, sys_mq_timedsend), // (mq_open+2)
sewardj8c9ea4e2005-06-08 10:46:56 +00002282
njn4279a882005-08-26 03:43:28 +00002283 LINXY(__NR_mq_timedreceive, sys_mq_timedreceive),// (mq_open+3)
2284 LINX_(__NR_mq_notify, sys_mq_notify), // (mq_open+4)
2285 LINXY(__NR_mq_getsetattr, sys_mq_getsetattr), // (mq_open+5)
nethercote8ff888f2004-11-17 17:11:45 +00002286 GENX_(__NR_sys_kexec_load, sys_ni_syscall), // 283
njncd405ea2005-08-31 02:44:31 +00002287 LINXY(__NR_waitid, sys_waitid), // 284
tom0bcaf2a2005-07-25 15:21:41 +00002288
2289 GENX_(285, sys_ni_syscall), // 285
2290// LINX_(__NR_add_key, sys_add_key), // 286
2291// LINX_(__NR_request_key, sys_request_key), // 287
2292// LINXY(__NR_keyctl, sys_keyctl), // 288
2293// LINX_(__NR_ioprio_set, sys_ioprio_set), // 289
2294
2295// LINX_(__NR_ioprio_get, sys_ioprio_get), // 290
2296 LINX_(__NR_inotify_init, sys_inotify_init), // 291
2297 LINX_(__NR_inotify_add_watch, sys_inotify_add_watch), // 292
2298 LINX_(__NR_inotify_rm_watch, sys_inotify_rm_watch), // 293
nethercote8ff888f2004-11-17 17:11:45 +00002299};
2300
njnaf839f52005-06-23 03:27:57 +00002301const UInt ML_(syscall_table_size) =
2302 sizeof(ML_(syscall_table)) / sizeof(ML_(syscall_table)[0]);
nethercote8ff888f2004-11-17 17:11:45 +00002303
nethercote41c75da2004-10-18 15:34:14 +00002304/*--------------------------------------------------------------------*/
2305/*--- end ---*/
2306/*--------------------------------------------------------------------*/