blob: bd355b9e8c604b55f979886b9189db917ed2fec7 [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"
njn899ce732005-06-21 00:28:11 +000038#include "pub_core_debuginfo.h" // Needed for pub_core_aspacemgr :(
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"
njne9befc62005-06-11 15:51:30 +000043#include "pub_core_libcmman.h"
njn36a20fa2005-06-03 03:08:39 +000044#include "pub_core_libcprint.h"
njnf39e9a32005-06-12 02:43:17 +000045#include "pub_core_libcproc.h"
njnde62cbf2005-06-10 22:08:14 +000046#include "pub_core_libcsignal.h"
njnf4c50162005-06-20 14:18:12 +000047#include "pub_core_main.h" // For VG_(shutdown_actions_NORETURN)()
njnaf1d7df2005-06-11 01:31:52 +000048#include "pub_core_mallocfree.h"
njnf4c50162005-06-20 14:18:12 +000049#include "pub_core_options.h"
njnc7561b92005-06-19 01:24:32 +000050#include "pub_core_scheduler.h"
njnf4c50162005-06-20 14:18:12 +000051#include "pub_core_sigframe.h" // For VG_(sigframe_destroy)()
njnde62cbf2005-06-10 22:08:14 +000052#include "pub_core_signals.h"
njn9abd6082005-06-17 21:31:45 +000053#include "pub_core_syscall.h"
njnc1b01812005-06-17 22:19:06 +000054#include "pub_core_syswrap.h"
njn43b9a8a2005-05-10 04:37:01 +000055#include "pub_core_tooliface.h"
sewardja8d8e232005-06-07 20:04:56 +000056
57#include "priv_types_n_macros.h"
njnc1b01812005-06-17 22:19:06 +000058#include "priv_syswrap-generic.h" /* for decls of generic wrappers */
59#include "priv_syswrap-linux.h" /* for decls of linux-ish wrappers */
60#include "priv_syswrap-main.h"
sewardja8d8e232005-06-07 20:04:56 +000061
62#include "vki_unistd.h" /* for the __NR_* constants */
sewardj55f9d1a2005-04-25 11:11:44 +000063
sewardj4d89e302005-03-16 22:04:40 +000064
65/* ---------------------------------------------------------------------
njn2335d112005-05-15 20:52:04 +000066 Stacks, thread wrappers
sewardj4d89e302005-03-16 22:04:40 +000067 Note. Why is this stuff here?
68 ------------------------------------------------------------------ */
69
sewardjb5f6f512005-03-10 23:59:00 +000070/*
71 Allocate a stack for this thread.
72
73 They're allocated lazily, but never freed.
74 */
75#define FILL 0xdeadbeef
76
njn45ed2c62005-05-16 21:39:23 +000077// Valgrind's stack size, in words.
78#define STACK_SIZE_W 16384
79
njn990e90c2005-04-05 02:49:09 +000080static UWord* allocstack(ThreadId tid)
sewardjb5f6f512005-03-10 23:59:00 +000081{
82 ThreadState *tst = VG_(get_ThreadState)(tid);
njn990e90c2005-04-05 02:49:09 +000083 UWord *esp;
sewardjb5f6f512005-03-10 23:59:00 +000084
njn990e90c2005-04-05 02:49:09 +000085 if (tst->os_state.valgrind_stack_base == 0) {
njn45ed2c62005-05-16 21:39:23 +000086 void *stk = VG_(mmap)(0, STACK_SIZE_W * sizeof(UWord) + VKI_PAGE_SIZE,
sewardjb5f6f512005-03-10 23:59:00 +000087 VKI_PROT_READ|VKI_PROT_WRITE,
88 VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS,
89 SF_VALGRIND,
90 -1, 0);
91
92 if (stk != (void *)-1) {
sewardja8d8e232005-06-07 20:04:56 +000093 VG_(mprotect)(stk, VKI_PAGE_SIZE, VKI_PROT_NONE); /* guard page */
94 tst->os_state.valgrind_stack_base = ((Addr)stk) + VKI_PAGE_SIZE;
95 tst->os_state.valgrind_stack_szB = STACK_SIZE_W * sizeof(UWord);
sewardjb5f6f512005-03-10 23:59:00 +000096 } else
sewardja8d8e232005-06-07 20:04:56 +000097 return (UWord*)-1;
sewardjb5f6f512005-03-10 23:59:00 +000098 }
99
njn990e90c2005-04-05 02:49:09 +0000100 for (esp = (UWord*) tst->os_state.valgrind_stack_base;
101 esp < (UWord*)(tst->os_state.valgrind_stack_base +
102 tst->os_state.valgrind_stack_szB);
103 esp++)
sewardjb5f6f512005-03-10 23:59:00 +0000104 *esp = FILL;
105 /* esp is left at top of stack */
106
107 if (0)
108 VG_(printf)("stack for tid %d at %p (%x); esp=%p\n",
njn990e90c2005-04-05 02:49:09 +0000109 tid, tst->os_state.valgrind_stack_base,
110 *(UWord*)(tst->os_state.valgrind_stack_base), esp);
sewardjb5f6f512005-03-10 23:59:00 +0000111
112 return esp;
113}
114
sewardj4d89e302005-03-16 22:04:40 +0000115/* NB: this is identical the the amd64 version. */
sewardjb5f6f512005-03-10 23:59:00 +0000116/* Return how many bytes of this stack have not been used */
njnaf839f52005-06-23 03:27:57 +0000117SSizeT VG_(stack_unused)(ThreadId tid)
sewardjb5f6f512005-03-10 23:59:00 +0000118{
119 ThreadState *tst = VG_(get_ThreadState)(tid);
njn990e90c2005-04-05 02:49:09 +0000120 UWord* p;
sewardjb5f6f512005-03-10 23:59:00 +0000121
njn990e90c2005-04-05 02:49:09 +0000122 for (p = (UWord*)tst->os_state.valgrind_stack_base;
123 p && (p < (UWord*)(tst->os_state.valgrind_stack_base +
124 tst->os_state.valgrind_stack_szB));
sewardjb5f6f512005-03-10 23:59:00 +0000125 p++)
126 if (*p != FILL)
127 break;
128
129 if (0)
njn990e90c2005-04-05 02:49:09 +0000130 VG_(printf)("p=%p %x tst->os_state.valgrind_stack_base=%p\n",
131 p, *p, tst->os_state.valgrind_stack_base);
sewardjb5f6f512005-03-10 23:59:00 +0000132
njn990e90c2005-04-05 02:49:09 +0000133 return ((Addr)p) - tst->os_state.valgrind_stack_base;
sewardjb5f6f512005-03-10 23:59:00 +0000134}
135
sewardj1d887112005-05-30 21:44:08 +0000136
137/* Run a thread all the way to the end, then do appropriate exit actions
138 (this is the last-one-out-turn-off-the-lights bit).
139*/
140static void run_a_thread_NORETURN ( Word tidW )
sewardjb5f6f512005-03-10 23:59:00 +0000141{
sewardj1d887112005-05-30 21:44:08 +0000142 ThreadId tid = (ThreadId)tidW;
143
njnc1b01812005-06-17 22:19:06 +0000144 VG_(debugLog)(1, "syswrap-x86-linux",
sewardj1d887112005-05-30 21:44:08 +0000145 "run_a_thread_NORETURN(tid=%lld): "
cerion7b2c38c2005-06-23 07:52:54 +0000146 "ML_(thread_wrapper) called\n",
sewardj1d887112005-05-30 21:44:08 +0000147 (ULong)tidW);
148
149 /* Run the thread all the way through. */
sewardj7eb7c582005-06-23 01:02:53 +0000150 VgSchedReturnCode src = ML_(thread_wrapper)(tid);
sewardj1d887112005-05-30 21:44:08 +0000151
njnc1b01812005-06-17 22:19:06 +0000152 VG_(debugLog)(1, "syswrap-x86-linux",
sewardj1d887112005-05-30 21:44:08 +0000153 "run_a_thread_NORETURN(tid=%lld): "
cerion7b2c38c2005-06-23 07:52:54 +0000154 "ML_(thread_wrapper) done\n",
sewardj1d887112005-05-30 21:44:08 +0000155 (ULong)tidW);
156
157 Int c = VG_(count_living_threads)();
158 vg_assert(c >= 1); /* stay sane */
159
160 if (c == 1) {
161
njnc1b01812005-06-17 22:19:06 +0000162 VG_(debugLog)(1, "syswrap-x86-linux",
sewardj1d887112005-05-30 21:44:08 +0000163 "run_a_thread_NORETURN(tid=%lld): "
164 "last one standing\n",
165 (ULong)tidW);
166
167 /* We are the last one standing. Keep hold of the lock and
168 carry on to show final tool results, then exit the entire system. */
169 VG_(shutdown_actions_NORETURN)(tid, src);
170
171 } else {
172
njnc1b01812005-06-17 22:19:06 +0000173 VG_(debugLog)(1, "syswrap-x86-linux",
sewardj1d887112005-05-30 21:44:08 +0000174 "run_a_thread_NORETURN(tid=%lld): "
175 "not last one standing\n",
176 (ULong)tidW);
177
178 /* OK, thread is dead, but others still exist. Just exit. */
179 ThreadState *tst = VG_(get_ThreadState)(tid);
180
181 /* This releases the run lock */
182 VG_(exit_thread)(tid);
183 vg_assert(tst->status == VgTs_Zombie);
184
185 /* We have to use this sequence to terminate the thread to
186 prevent a subtle race. If VG_(exit_thread)() had left the
187 ThreadState as Empty, then it could have been reallocated,
188 reusing the stack while we're doing these last cleanups.
189 Instead, VG_(exit_thread) leaves it as Zombie to prevent
190 reallocation. We need to make sure we don't touch the stack
191 between marking it Empty and exiting. Hence the
192 assembler. */
193 asm volatile (
194 "movl %1, %0\n" /* set tst->status = VgTs_Empty */
195 "movl %2, %%eax\n" /* set %eax = __NR_exit */
196 "movl %3, %%ebx\n" /* set %ebx = tst->os_state.exitcode */
197 "int $0x80\n" /* exit(tst->os_state.exitcode) */
198 : "=m" (tst->status)
199 : "n" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode));
200
201 VG_(core_panic)("Thread exit failed?\n");
202 }
203
204 /*NOTREACHED*/
205 vg_assert(0);
206}
207
208
njnfcb7c3e2005-06-18 15:54:25 +0000209/* Call f(arg1), but first switch stacks, using 'stack' as the new
210 stack, and use 'retaddr' as f's return-to address. Also, clear all
211 the integer registers before entering f.*/
212__attribute__((noreturn))
213void call_on_new_stack_0_1 ( Addr stack,
214 Addr retaddr,
215 void (*f)(Word),
216 Word arg1 );
217// 4(%esp) == stack
218// 8(%esp) == retaddr
219// 12(%esp) == f
220// 16(%esp) == arg1
221asm(
222"call_on_new_stack_0_1:\n"
223" movl %esp, %esi\n" // remember old stack pointer
224" movl 4(%esi), %esp\n" // set stack
225" pushl 16(%esi)\n" // arg1 to stack
226" pushl 8(%esi)\n" // retaddr to stack
227" pushl 12(%esi)\n" // f to stack
228" movl $0, %eax\n" // zero all GP regs
229" movl $0, %ebx\n"
230" movl $0, %ecx\n"
231" movl $0, %edx\n"
232" movl $0, %esi\n"
233" movl $0, %edi\n"
234" movl $0, %ebp\n"
235" ret\n" // jump to f
236" ud2\n" // should never get here
237);
238
239
sewardj1d887112005-05-30 21:44:08 +0000240/*
241 Allocate a stack for the main thread, and run it all the way to the
242 end.
243*/
njnaf839f52005-06-23 03:27:57 +0000244void VG_(main_thread_wrapper_NORETURN)(ThreadId tid)
sewardj1d887112005-05-30 21:44:08 +0000245{
njnc1b01812005-06-17 22:19:06 +0000246 VG_(debugLog)(1, "syswrap-x86-linux",
njnaf839f52005-06-23 03:27:57 +0000247 "entering VG_(main_thread_wrapper_NORETURN)\n");
sewardj1d887112005-05-30 21:44:08 +0000248
njn990e90c2005-04-05 02:49:09 +0000249 UWord* esp = allocstack(tid);
sewardjb5f6f512005-03-10 23:59:00 +0000250
sewardj1d887112005-05-30 21:44:08 +0000251 /* shouldn't be any other threads around yet */
252 vg_assert( VG_(count_living_threads)() == 1 );
sewardjb5f6f512005-03-10 23:59:00 +0000253
sewardj7f082a62005-03-22 01:55:35 +0000254 call_on_new_stack_0_1(
sewardj1d887112005-05-30 21:44:08 +0000255 (Addr)esp, /* stack */
256 0, /*bogus return address*/
257 run_a_thread_NORETURN, /* fn to call */
258 (Word)tid /* arg to give it */
sewardj7f082a62005-03-22 01:55:35 +0000259 );
260
261 /*NOTREACHED*/
262 vg_assert(0);
sewardjb5f6f512005-03-10 23:59:00 +0000263}
264
sewardj1d887112005-05-30 21:44:08 +0000265
266static Int start_thread_NORETURN ( void* arg )
sewardjb5f6f512005-03-10 23:59:00 +0000267{
sewardj1d887112005-05-30 21:44:08 +0000268 ThreadState* tst = (ThreadState*)arg;
269 ThreadId tid = tst->tid;
sewardjb5f6f512005-03-10 23:59:00 +0000270
sewardj1d887112005-05-30 21:44:08 +0000271 run_a_thread_NORETURN ( (Word)tid );
272 /*NOTREACHED*/
273 vg_assert(0);
sewardjb5f6f512005-03-10 23:59:00 +0000274}
275
sewardj1d887112005-05-30 21:44:08 +0000276
njn2335d112005-05-15 20:52:04 +0000277/* ---------------------------------------------------------------------
sewardjb5f6f512005-03-10 23:59:00 +0000278 clone() handling
njn2335d112005-05-15 20:52:04 +0000279 ------------------------------------------------------------------ */
sewardjb5f6f512005-03-10 23:59:00 +0000280
sewardja8d8e232005-06-07 20:04:56 +0000281/*
282 Perform a clone system call. clone is strange because it has
283 fork()-like return-twice semantics, so it needs special
284 handling here.
285
286 Upon entry, we have:
287
288 int (fn)(void*) in 0+FSZ(%esp)
289 void* child_stack in 4+FSZ(%esp)
290 int flags in 8+FSZ(%esp)
291 void* arg in 12+FSZ(%esp)
292 pid_t* child_tid in 16+FSZ(%esp)
293 pid_t* parent_tid in 20+FSZ(%esp)
294 void* tls_ptr in 24+FSZ(%esp)
295
296 System call requires:
297
298 int $__NR_clone in %eax
299 int flags in %ebx
300 void* child_stack in %ecx
301 pid_t* parent_tid in %edx
302 pid_t* child_tid in %edi
303 void* tls_ptr in %esi
304
305 Returns an Int encoded in the linux-x86 way, not a SysRes.
306 */
307#define STRINGIFZ(__str) #__str
308#define STRINGIFY(__str) STRINGIFZ(__str)
309#define FSZ "4+4+4" /* frame size = retaddr+ebx+edi */
310#define __NR_CLONE STRINGIFY(__NR_clone)
311#define __NR_EXIT STRINGIFY(__NR_exit)
312
313extern
314Int do_syscall_clone_x86_linux ( Int (*fn)(void *),
315 void* stack,
316 Int flags,
317 void* arg,
318 Int* child_tid,
319 Int* parent_tid,
320 vki_modify_ldt_t * );
321asm(
322"\n"
323"do_syscall_clone_x86_linux:\n"
324" push %ebx\n"
325" push %edi\n"
326
327 /* set up child stack with function and arg */
328" movl 4+"FSZ"(%esp), %ecx\n" /* syscall arg2: child stack */
329" movl 12+"FSZ"(%esp), %ebx\n" /* fn arg */
330" movl 0+"FSZ"(%esp), %eax\n" /* fn */
331" lea -8(%ecx), %ecx\n" /* make space on stack */
332" movl %ebx, 4(%ecx)\n" /* fn arg */
333" movl %eax, 0(%ecx)\n" /* fn */
334
335 /* get other args to clone */
336" movl 8+"FSZ"(%esp), %ebx\n" /* syscall arg1: flags */
337" movl 20+"FSZ"(%esp), %edx\n" /* syscall arg3: parent tid * */
338" movl 16+"FSZ"(%esp), %edi\n" /* syscall arg4: child tid * */
339" movl 24+"FSZ"(%esp), %esi\n" /* syscall arg5: tls_ptr * */
340" movl $"__NR_CLONE", %eax\n"
341" int $0x80\n" /* clone() */
342" testl %eax, %eax\n" /* child if retval == 0 */
343" jnz 1f\n"
344
345 /* CHILD - call thread function */
346" popl %eax\n"
347" call *%eax\n" /* call fn */
348
349 /* exit with result */
350" movl %eax, %ebx\n" /* arg1: return value from fn */
351" movl $"__NR_EXIT", %eax\n"
352" int $0x80\n"
353
354 /* Hm, exit returned */
355" ud2\n"
356
sewardje7aa4ae2005-06-09 12:43:42 +0000357"1:\n" /* PARENT or ERROR */
sewardja8d8e232005-06-07 20:04:56 +0000358" pop %edi\n"
359" pop %ebx\n"
360" ret\n"
361);
362
363#undef FSZ
364#undef __NR_CLONE
365#undef __NR_EXIT
366#undef STRINGIFY
367#undef STRINGIFZ
368
sewardje7aa4ae2005-06-09 12:43:42 +0000369
njn2335d112005-05-15 20:52:04 +0000370// forward declarations
sewardj468dc792005-05-31 10:12:06 +0000371static void setup_child ( ThreadArchState*, ThreadArchState*, Bool );
sewardja8d8e232005-06-07 20:04:56 +0000372static SysRes sys_set_thread_area ( ThreadId, vki_modify_ldt_t* );
njn2335d112005-05-15 20:52:04 +0000373
374/*
sewardjb5f6f512005-03-10 23:59:00 +0000375 When a client clones, we need to keep track of the new thread. This means:
376 1. allocate a ThreadId+ThreadState+stack for the the thread
377
378 2. initialize the thread's new VCPU state
379
380 3. create the thread using the same args as the client requested,
381 but using the scheduler entrypoint for EIP, and a separate stack
382 for ESP.
383 */
sewardja8d8e232005-06-07 20:04:56 +0000384static SysRes do_clone ( ThreadId ptid,
385 UInt flags, Addr esp,
sewardje7aa4ae2005-06-09 12:43:42 +0000386 Int* parent_tidptr,
387 Int* child_tidptr,
sewardja8d8e232005-06-07 20:04:56 +0000388 vki_modify_ldt_t *tlsinfo)
sewardjb5f6f512005-03-10 23:59:00 +0000389{
390 static const Bool debug = False;
391
sewardja8d8e232005-06-07 20:04:56 +0000392 ThreadId ctid = VG_(alloc_ThreadState)();
393 ThreadState* ptst = VG_(get_ThreadState)(ptid);
394 ThreadState* ctst = VG_(get_ThreadState)(ctid);
395 UWord* stack;
396 Segment* seg;
397 SysRes res;
398 Int eax;
sewardjb5f6f512005-03-10 23:59:00 +0000399 vki_sigset_t blockall, savedmask;
400
401 VG_(sigfillset)(&blockall);
402
403 vg_assert(VG_(is_running_thread)(ptid));
404 vg_assert(VG_(is_valid_tid)(ctid));
405
406 stack = allocstack(ctid);
407
408 /* Copy register state
409
410 Both parent and child return to the same place, and the code
411 following the clone syscall works out which is which, so we
412 don't need to worry about it.
413
414 The parent gets the child's new tid returned from clone, but the
415 child gets 0.
416
417 If the clone call specifies a NULL esp for the new thread, then
418 it actually gets a copy of the parent's esp.
419 */
sewardj468dc792005-05-31 10:12:06 +0000420 /* HACK: The clone call done by the Quadrics Elan3 driver specifies
421 clone flags of 0xF00, and it seems to rely on the assumption
422 that the child inherits a copy of the parent's GDT. Hence that
423 is passed as an arg to setup_child. */
sewardj934d2d52005-05-31 13:08:03 +0000424 setup_child( &ctst->arch, &ptst->arch, True /*VG_(clo_support_elan3)*/ );
sewardjb5f6f512005-03-10 23:59:00 +0000425
sewardje7aa4ae2005-06-09 12:43:42 +0000426 /* Make sys_clone appear to have returned Success(0) in the
427 child. */
sewardja8d8e232005-06-07 20:04:56 +0000428 ctst->arch.vex.guest_EAX = 0;
429
sewardjb5f6f512005-03-10 23:59:00 +0000430 if (esp != 0)
431 ctst->arch.vex.guest_ESP = esp;
432
433 ctst->os_state.parent = ptid;
sewardjb5f6f512005-03-10 23:59:00 +0000434
435 /* inherit signal mask */
njnaffd8782005-05-18 22:56:00 +0000436 ctst->sig_mask = ptst->sig_mask;
sewardjb5f6f512005-03-10 23:59:00 +0000437 ctst->tmp_sig_mask = ptst->sig_mask;
438
439 /* We don't really know where the client stack is, because its
440 allocated by the client. The best we can do is look at the
441 memory mappings and try to derive some useful information. We
442 assume that esp starts near its highest possible value, and can
443 only go down to the start of the mmaped segment. */
444 seg = VG_(find_segment)((Addr)esp);
445 if (seg) {
njn13bfd852005-06-02 03:52:53 +0000446 ctst->client_stack_highest_word = (Addr)VG_PGROUNDUP(esp);
njn50ba34e2005-04-04 02:41:42 +0000447 ctst->client_stack_szB = ctst->client_stack_highest_word - seg->addr;
sewardjb5f6f512005-03-10 23:59:00 +0000448
449 if (debug)
450 VG_(printf)("tid %d: guessed client stack range %p-%p\n",
njn13bfd852005-06-02 03:52:53 +0000451 ctid, seg->addr, VG_PGROUNDUP(esp));
sewardjb5f6f512005-03-10 23:59:00 +0000452 } else {
453 VG_(message)(Vg_UserMsg, "!? New thread %d starts with ESP(%p) unmapped\n",
454 ctid, esp);
njn50ba34e2005-04-04 02:41:42 +0000455 ctst->client_stack_szB = 0;
sewardjb5f6f512005-03-10 23:59:00 +0000456 }
457
458 if (flags & VKI_CLONE_SETTLS) {
459 if (debug)
sewardja8d8e232005-06-07 20:04:56 +0000460 VG_(printf)("clone child has SETTLS: tls info at %p: idx=%d "
461 "base=%p limit=%x; esp=%p fs=%x gs=%x\n",
462 tlsinfo, tlsinfo->entry_number,
463 tlsinfo->base_addr, tlsinfo->limit,
sewardjb5f6f512005-03-10 23:59:00 +0000464 ptst->arch.vex.guest_ESP,
465 ctst->arch.vex.guest_FS, ctst->arch.vex.guest_GS);
sewardja8d8e232005-06-07 20:04:56 +0000466 res = sys_set_thread_area(ctid, tlsinfo);
467 if (res.isError)
sewardjb5f6f512005-03-10 23:59:00 +0000468 goto out;
469 }
470
471 flags &= ~VKI_CLONE_SETTLS;
472
473 /* start the thread with everything blocked */
474 VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
475
476 /* Create the new thread */
sewardja8d8e232005-06-07 20:04:56 +0000477 eax = do_syscall_clone_x86_linux(
478 start_thread_NORETURN, stack, flags, &VG_(threads)[ctid],
479 child_tidptr, parent_tidptr, NULL
480 );
cerion85665ca2005-06-20 15:51:07 +0000481 res = VG_(mk_SysRes_x86_linux)( eax );
sewardje7aa4ae2005-06-09 12:43:42 +0000482
sewardjb5f6f512005-03-10 23:59:00 +0000483 VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
484
485 out:
sewardja8d8e232005-06-07 20:04:56 +0000486 if (res.isError) {
sewardjb5f6f512005-03-10 23:59:00 +0000487 /* clone failed */
njnaf839f52005-06-23 03:27:57 +0000488 VG_(cleanup_thread)(&ctst->arch);
sewardjb5f6f512005-03-10 23:59:00 +0000489 ctst->status = VgTs_Empty;
490 }
491
sewardja8d8e232005-06-07 20:04:56 +0000492 return res;
sewardjb5f6f512005-03-10 23:59:00 +0000493}
494
sewardja8d8e232005-06-07 20:04:56 +0000495
sewardjb5f6f512005-03-10 23:59:00 +0000496/* Do a clone which is really a fork() */
sewardja8d8e232005-06-07 20:04:56 +0000497static SysRes do_fork_clone ( ThreadId tid,
498 UInt flags, Addr esp,
499 Int* parent_tidptr,
500 Int* child_tidptr )
sewardjb5f6f512005-03-10 23:59:00 +0000501{
502 vki_sigset_t fork_saved_mask;
503 vki_sigset_t mask;
sewardja8d8e232005-06-07 20:04:56 +0000504 SysRes res;
sewardjb5f6f512005-03-10 23:59:00 +0000505
sewardja8d8e232005-06-07 20:04:56 +0000506 if (flags & (VKI_CLONE_SETTLS | VKI_CLONE_FS | VKI_CLONE_VM
507 | VKI_CLONE_FILES | VKI_CLONE_VFORK))
508 return VG_(mk_SysRes_Error)( VKI_EINVAL );
sewardjb5f6f512005-03-10 23:59:00 +0000509
510 /* Block all signals during fork, so that we can fix things up in
511 the child without being interrupted. */
512 VG_(sigfillset)(&mask);
513 VG_(sigprocmask)(VKI_SIG_SETMASK, &mask, &fork_saved_mask);
514
sewardjb5f6f512005-03-10 23:59:00 +0000515 /* Since this is the fork() form of clone, we don't need all that
516 VG_(clone) stuff */
sewardje7aa4ae2005-06-09 12:43:42 +0000517 res = VG_(do_syscall5)( __NR_clone, flags,
518 (UWord)NULL, (UWord)parent_tidptr,
519 (UWord)NULL, (UWord)child_tidptr );
sewardjb5f6f512005-03-10 23:59:00 +0000520
sewardja8d8e232005-06-07 20:04:56 +0000521 if (!res.isError && res.val == 0) {
sewardjb5f6f512005-03-10 23:59:00 +0000522 /* child */
523 VG_(do_atfork_child)(tid);
524
525 /* restore signal mask */
526 VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
sewardja8d8e232005-06-07 20:04:56 +0000527 }
528 else
529 if (!res.isError && res.val > 0) {
sewardjb5f6f512005-03-10 23:59:00 +0000530 /* parent */
531 if (VG_(clo_trace_syscalls))
sewardja8d8e232005-06-07 20:04:56 +0000532 VG_(printf)(" clone(fork): process %d created child %d\n",
533 VG_(getpid)(), res.val);
sewardjb5f6f512005-03-10 23:59:00 +0000534
sewardjb5f6f512005-03-10 23:59:00 +0000535 /* restore signal mask */
536 VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
537 }
538
sewardja8d8e232005-06-07 20:04:56 +0000539 return res;
sewardjb5f6f512005-03-10 23:59:00 +0000540}
541
nethercote8ff888f2004-11-17 17:11:45 +0000542/* ---------------------------------------------------------------------
njn2335d112005-05-15 20:52:04 +0000543 LDT/GDT simulation
544 ------------------------------------------------------------------ */
545
546/* Details of the LDT simulation
547 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
548
549 When a program runs natively, the linux kernel allows each *thread*
550 in it to have its own LDT. Almost all programs never do this --
551 it's wildly unportable, after all -- and so the kernel never
552 allocates the structure, which is just as well as an LDT occupies
553 64k of memory (8192 entries of size 8 bytes).
554
555 A thread may choose to modify its LDT entries, by doing the
556 __NR_modify_ldt syscall. In such a situation the kernel will then
557 allocate an LDT structure for it. Each LDT entry is basically a
558 (base, limit) pair. A virtual address in a specific segment is
559 translated to a linear address by adding the segment's base value.
560 In addition, the virtual address must not exceed the limit value.
561
562 To use an LDT entry, a thread loads one of the segment registers
563 (%cs, %ss, %ds, %es, %fs, %gs) with the index of the LDT entry (0
564 .. 8191) it wants to use. In fact, the required value is (index <<
565 3) + 7, but that's not important right now. Any normal instruction
566 which includes an addressing mode can then be made relative to that
567 LDT entry by prefixing the insn with a so-called segment-override
568 prefix, a byte which indicates which of the 6 segment registers
569 holds the LDT index.
570
571 Now, a key constraint is that valgrind's address checks operate in
572 terms of linear addresses. So we have to explicitly translate
573 virtual addrs into linear addrs, and that means doing a complete
574 LDT simulation.
575
576 Calls to modify_ldt are intercepted. For each thread, we maintain
577 an LDT (with the same normally-never-allocated optimisation that
578 the kernel does). This is updated as expected via calls to
579 modify_ldt.
580
581 When a thread does an amode calculation involving a segment
582 override prefix, the relevant LDT entry for the thread is
583 consulted. It all works.
584
585 There is a conceptual problem, which appears when switching back to
586 native execution, either temporarily to pass syscalls to the
587 kernel, or permanently, when debugging V. Problem at such points
588 is that it's pretty pointless to copy the simulated machine's
589 segment registers to the real machine, because we'd also need to
590 copy the simulated LDT into the real one, and that's prohibitively
591 expensive.
592
593 Fortunately it looks like no syscalls rely on the segment regs or
594 LDT being correct, so we can get away with it. Apart from that the
595 simulation is pretty straightforward. All 6 segment registers are
596 tracked, although only %ds, %es, %fs and %gs are allowed as
597 prefixes. Perhaps it could be restricted even more than that -- I
598 am not sure what is and isn't allowed in user-mode.
599*/
600
601/* Translate a struct modify_ldt_ldt_s to a VexGuestX86SegDescr, using
602 the Linux kernel's logic (cut-n-paste of code in
603 linux/kernel/ldt.c). */
604
605static
606void translate_to_hw_format ( /* IN */ vki_modify_ldt_t* inn,
sewardja8d8e232005-06-07 20:04:56 +0000607 /* OUT */ VexGuestX86SegDescr* out,
njn2335d112005-05-15 20:52:04 +0000608 Int oldmode )
609{
610 UInt entry_1, entry_2;
611 vg_assert(8 == sizeof(VexGuestX86SegDescr));
612
613 if (0)
614 VG_(printf)("translate_to_hw_format: base %p, limit %d\n",
615 inn->base_addr, inn->limit );
616
617 /* Allow LDTs to be cleared by the user. */
618 if (inn->base_addr == 0 && inn->limit == 0) {
619 if (oldmode ||
620 (inn->contents == 0 &&
621 inn->read_exec_only == 1 &&
622 inn->seg_32bit == 0 &&
623 inn->limit_in_pages == 0 &&
624 inn->seg_not_present == 1 &&
625 inn->useable == 0 )) {
626 entry_1 = 0;
627 entry_2 = 0;
628 goto install;
629 }
630 }
631
632 entry_1 = ((inn->base_addr & 0x0000ffff) << 16) |
633 (inn->limit & 0x0ffff);
634 entry_2 = (inn->base_addr & 0xff000000) |
635 ((inn->base_addr & 0x00ff0000) >> 16) |
636 (inn->limit & 0xf0000) |
637 ((inn->read_exec_only ^ 1) << 9) |
638 (inn->contents << 10) |
639 ((inn->seg_not_present ^ 1) << 15) |
640 (inn->seg_32bit << 22) |
641 (inn->limit_in_pages << 23) |
642 0x7000;
643 if (!oldmode)
644 entry_2 |= (inn->useable << 20);
645
646 /* Install the new entry ... */
647 install:
648 out->LdtEnt.Words.word1 = entry_1;
649 out->LdtEnt.Words.word2 = entry_2;
650}
651
652/* Create a zeroed-out GDT. */
653static VexGuestX86SegDescr* alloc_zeroed_x86_GDT ( void )
654{
655 Int nbytes = VEX_GUEST_X86_GDT_NENT * sizeof(VexGuestX86SegDescr);
656 return VG_(arena_calloc)(VG_AR_CORE, nbytes, 1);
657}
658
659/* Create a zeroed-out LDT. */
660static VexGuestX86SegDescr* alloc_zeroed_x86_LDT ( void )
661{
662 Int nbytes = VEX_GUEST_X86_LDT_NENT * sizeof(VexGuestX86SegDescr);
663 return VG_(arena_calloc)(VG_AR_CORE, nbytes, 1);
664}
665
666/* Free up an LDT or GDT allocated by the above fns. */
667static void free_LDT_or_GDT ( VexGuestX86SegDescr* dt )
668{
669 vg_assert(dt);
670 VG_(arena_free)(VG_AR_CORE, (void*)dt);
671}
672
673/* Copy contents between two existing LDTs. */
674static void copy_LDT_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_LDT_NENT; i++)
681 dst[i] = src[i];
njn2335d112005-05-15 20:52:04 +0000682}
683
sewardj468dc792005-05-31 10:12:06 +0000684/* Copy contents between two existing GDTs. */
685static void copy_GDT_from_to ( VexGuestX86SegDescr* src,
686 VexGuestX86SegDescr* dst )
687{
sewardja8d8e232005-06-07 20:04:56 +0000688 Int i;
689 vg_assert(src);
690 vg_assert(dst);
691 for (i = 0; i < VEX_GUEST_X86_GDT_NENT; i++)
692 dst[i] = src[i];
sewardj468dc792005-05-31 10:12:06 +0000693}
694
njn2335d112005-05-15 20:52:04 +0000695/* Free this thread's DTs, if it has any. */
696static void deallocate_LGDTs_for_thread ( VexGuestX86State* vex )
697{
698 vg_assert(sizeof(HWord) == sizeof(void*));
699
700 if (0)
701 VG_(printf)("deallocate_LGDTs_for_thread: "
702 "ldt = 0x%x, gdt = 0x%x\n",
703 vex->guest_LDT, vex->guest_GDT );
704
705 if (vex->guest_LDT != (HWord)NULL) {
706 free_LDT_or_GDT( (VexGuestX86SegDescr*)vex->guest_LDT );
707 vex->guest_LDT = (HWord)NULL;
708 }
709
710 if (vex->guest_GDT != (HWord)NULL) {
711 free_LDT_or_GDT( (VexGuestX86SegDescr*)vex->guest_GDT );
712 vex->guest_GDT = (HWord)NULL;
713 }
714}
715
716
717/*
718 * linux/kernel/ldt.c
719 *
720 * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds
721 * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
722 */
723
724/*
725 * read_ldt() is not really atomic - this is not a problem since
726 * synchronization of reads and writes done to the LDT has to be
727 * assured by user-space anyway. Writes are atomic, to protect
728 * the security checks done on new descriptors.
729 */
730static
sewardja8d8e232005-06-07 20:04:56 +0000731SysRes read_ldt ( ThreadId tid, UChar* ptr, UInt bytecount )
njn2335d112005-05-15 20:52:04 +0000732{
sewardja8d8e232005-06-07 20:04:56 +0000733 SysRes res;
njn2335d112005-05-15 20:52:04 +0000734 UInt i, size;
735 UChar* ldt;
736
737 if (0)
738 VG_(printf)("read_ldt: tid = %d, ptr = %p, bytecount = %d\n",
739 tid, ptr, bytecount );
740
741 vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*));
742 vg_assert(8 == sizeof(VexGuestX86SegDescr));
743
744 ldt = (Char*)(VG_(threads)[tid].arch.vex.guest_LDT);
sewardja8d8e232005-06-07 20:04:56 +0000745 res = VG_(mk_SysRes_Success)( 0 );
njn2335d112005-05-15 20:52:04 +0000746 if (ldt == NULL)
747 /* LDT not allocated, meaning all entries are null */
748 goto out;
749
750 size = VEX_GUEST_X86_LDT_NENT * sizeof(VexGuestX86SegDescr);
751 if (size > bytecount)
752 size = bytecount;
753
sewardja8d8e232005-06-07 20:04:56 +0000754 res = VG_(mk_SysRes_Success)( size );
njn2335d112005-05-15 20:52:04 +0000755 for (i = 0; i < size; i++)
756 ptr[i] = ldt[i];
757
758 out:
sewardja8d8e232005-06-07 20:04:56 +0000759 return res;
njn2335d112005-05-15 20:52:04 +0000760}
761
762
763static
sewardja8d8e232005-06-07 20:04:56 +0000764SysRes write_ldt ( ThreadId tid, void* ptr, UInt bytecount, Int oldmode )
njn2335d112005-05-15 20:52:04 +0000765{
sewardja8d8e232005-06-07 20:04:56 +0000766 SysRes res;
njn2335d112005-05-15 20:52:04 +0000767 VexGuestX86SegDescr* ldt;
768 vki_modify_ldt_t* ldt_info;
769
770 if (0)
771 VG_(printf)("write_ldt: tid = %d, ptr = %p, "
772 "bytecount = %d, oldmode = %d\n",
773 tid, ptr, bytecount, oldmode );
774
775 vg_assert(8 == sizeof(VexGuestX86SegDescr));
776 vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*));
777
778 ldt = (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_LDT;
779 ldt_info = (vki_modify_ldt_t*)ptr;
780
sewardja8d8e232005-06-07 20:04:56 +0000781 res = VG_(mk_SysRes_Error)( VKI_EINVAL );
njn2335d112005-05-15 20:52:04 +0000782 if (bytecount != sizeof(vki_modify_ldt_t))
783 goto out;
784
sewardja8d8e232005-06-07 20:04:56 +0000785 res = VG_(mk_SysRes_Error)( VKI_EINVAL );
njn2335d112005-05-15 20:52:04 +0000786 if (ldt_info->entry_number >= VEX_GUEST_X86_LDT_NENT)
787 goto out;
788 if (ldt_info->contents == 3) {
789 if (oldmode)
790 goto out;
791 if (ldt_info->seg_not_present == 0)
792 goto out;
793 }
794
795 /* If this thread doesn't have an LDT, we'd better allocate it
796 now. */
797 if (ldt == (HWord)NULL) {
798 ldt = alloc_zeroed_x86_LDT();
799 VG_(threads)[tid].arch.vex.guest_LDT = (HWord)ldt;
800 }
801
802 /* Install the new entry ... */
803 translate_to_hw_format ( ldt_info, &ldt[ldt_info->entry_number], oldmode );
sewardja8d8e232005-06-07 20:04:56 +0000804 res = VG_(mk_SysRes_Success)( 0 );
njn2335d112005-05-15 20:52:04 +0000805
806 out:
sewardja8d8e232005-06-07 20:04:56 +0000807 return res;
njn2335d112005-05-15 20:52:04 +0000808}
809
810
sewardja8d8e232005-06-07 20:04:56 +0000811static SysRes sys_modify_ldt ( ThreadId tid,
812 Int func, void* ptr, UInt bytecount )
njn2335d112005-05-15 20:52:04 +0000813{
sewardja8d8e232005-06-07 20:04:56 +0000814 SysRes ret = VG_(mk_SysRes_Error)( VKI_ENOSYS );
njn2335d112005-05-15 20:52:04 +0000815
816 switch (func) {
817 case 0:
818 ret = read_ldt(tid, ptr, bytecount);
819 break;
820 case 1:
821 ret = write_ldt(tid, ptr, bytecount, 1);
822 break;
823 case 2:
824 VG_(unimplemented)("sys_modify_ldt: func == 2");
825 /* god knows what this is about */
826 /* ret = read_default_ldt(ptr, bytecount); */
827 /*UNREACHED*/
828 break;
829 case 0x11:
830 ret = write_ldt(tid, ptr, bytecount, 0);
831 break;
832 }
833 return ret;
834}
835
836
sewardja8d8e232005-06-07 20:04:56 +0000837static SysRes sys_set_thread_area ( ThreadId tid, vki_modify_ldt_t* info )
njn2335d112005-05-15 20:52:04 +0000838{
sewardja8d8e232005-06-07 20:04:56 +0000839 Int idx;
njn2335d112005-05-15 20:52:04 +0000840 VexGuestX86SegDescr* gdt;
841
842 vg_assert(8 == sizeof(VexGuestX86SegDescr));
843 vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*));
844
845 if (info == NULL)
sewardja8d8e232005-06-07 20:04:56 +0000846 return VG_(mk_SysRes_Error)( VKI_EFAULT );
njn2335d112005-05-15 20:52:04 +0000847
848 gdt = (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_GDT;
849
850 /* If the thread doesn't have a GDT, allocate it now. */
851 if (!gdt) {
852 gdt = alloc_zeroed_x86_GDT();
853 VG_(threads)[tid].arch.vex.guest_GDT = (HWord)gdt;
854 }
855
856 idx = info->entry_number;
857
858 if (idx == -1) {
859 /* Find and use the first free entry. */
860 for (idx = 0; idx < VEX_GUEST_X86_GDT_NENT; idx++) {
861 if (gdt[idx].LdtEnt.Words.word1 == 0
862 && gdt[idx].LdtEnt.Words.word2 == 0)
863 break;
864 }
865
866 if (idx == VEX_GUEST_X86_GDT_NENT)
sewardja8d8e232005-06-07 20:04:56 +0000867 return VG_(mk_SysRes_Error)( VKI_ESRCH );
njn2335d112005-05-15 20:52:04 +0000868 } else if (idx < 0 || idx >= VEX_GUEST_X86_GDT_NENT) {
sewardja8d8e232005-06-07 20:04:56 +0000869 return VG_(mk_SysRes_Error)( VKI_EINVAL );
njn2335d112005-05-15 20:52:04 +0000870 }
871
872 translate_to_hw_format(info, &gdt[idx], 0);
873
874 VG_TRACK( pre_mem_write, Vg_CoreSysCall, tid,
875 "set_thread_area(info->entry)",
876 (Addr) & info->entry_number, sizeof(unsigned int) );
877 info->entry_number = idx;
878 VG_TRACK( post_mem_write, Vg_CoreSysCall, tid,
879 (Addr) & info->entry_number, sizeof(unsigned int) );
880
sewardja8d8e232005-06-07 20:04:56 +0000881 return VG_(mk_SysRes_Success)( 0 );
njn2335d112005-05-15 20:52:04 +0000882}
883
884
sewardje6d5e722005-06-10 10:27:55 +0000885static SysRes sys_get_thread_area ( ThreadId tid, vki_modify_ldt_t* info )
886{
887 Int idx;
888 VexGuestX86SegDescr* gdt;
889
890 vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*));
891 vg_assert(8 == sizeof(VexGuestX86SegDescr));
892
893 if (info == NULL)
894 return VG_(mk_SysRes_Error)( VKI_EFAULT );
895
896 idx = info->entry_number;
897
898 if (idx < 0 || idx >= VEX_GUEST_X86_GDT_NENT)
899 return VG_(mk_SysRes_Error)( VKI_EINVAL );
900
901 gdt = (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_GDT;
902
903 /* If the thread doesn't have a GDT, allocate it now. */
904 if (!gdt) {
905 gdt = alloc_zeroed_x86_GDT();
906 VG_(threads)[tid].arch.vex.guest_GDT = (HWord)gdt;
907 }
908
909 info->base_addr = ( gdt[idx].LdtEnt.Bits.BaseHi << 24 ) |
910 ( gdt[idx].LdtEnt.Bits.BaseMid << 16 ) |
911 gdt[idx].LdtEnt.Bits.BaseLow;
912 info->limit = ( gdt[idx].LdtEnt.Bits.LimitHi << 16 ) |
913 gdt[idx].LdtEnt.Bits.LimitLow;
914 info->seg_32bit = gdt[idx].LdtEnt.Bits.Default_Big;
915 info->contents = ( gdt[idx].LdtEnt.Bits.Type >> 2 ) & 0x3;
916 info->read_exec_only = ( gdt[idx].LdtEnt.Bits.Type & 0x1 ) ^ 0x1;
917 info->limit_in_pages = gdt[idx].LdtEnt.Bits.Granularity;
918 info->seg_not_present = gdt[idx].LdtEnt.Bits.Pres ^ 0x1;
919 info->useable = gdt[idx].LdtEnt.Bits.Sys;
920 info->reserved = 0;
921
922 return VG_(mk_SysRes_Error)( 0 );
923}
njn2335d112005-05-15 20:52:04 +0000924
925/* ---------------------------------------------------------------------
926 More thread stuff
927 ------------------------------------------------------------------ */
928
njnaf839f52005-06-23 03:27:57 +0000929void VG_(cleanup_thread) ( ThreadArchState* arch )
njn2335d112005-05-15 20:52:04 +0000930{
931 /* Release arch-specific resources held by this thread. */
932 /* On x86, we have to dump the LDT and GDT. */
933 deallocate_LGDTs_for_thread( &arch->vex );
934}
935
936
937static void setup_child ( /*OUT*/ ThreadArchState *child,
sewardj468dc792005-05-31 10:12:06 +0000938 /*IN*/ ThreadArchState *parent,
939 Bool inherit_parents_GDT )
njn2335d112005-05-15 20:52:04 +0000940{
941 /* We inherit our parent's guest state. */
942 child->vex = parent->vex;
943 child->vex_shadow = parent->vex_shadow;
sewardj468dc792005-05-31 10:12:06 +0000944
njn2335d112005-05-15 20:52:04 +0000945 /* We inherit our parent's LDT. */
946 if (parent->vex.guest_LDT == (HWord)NULL) {
947 /* We hope this is the common case. */
948 child->vex.guest_LDT = (HWord)NULL;
949 } else {
950 /* No luck .. we have to take a copy of the parent's. */
951 child->vex.guest_LDT = (HWord)alloc_zeroed_x86_LDT();
952 copy_LDT_from_to( (VexGuestX86SegDescr*)parent->vex.guest_LDT,
953 (VexGuestX86SegDescr*)child->vex.guest_LDT );
954 }
955
sewardj468dc792005-05-31 10:12:06 +0000956 /* Either we start with an empty GDT (the usual case) or inherit a
957 copy of our parents' one (Quadrics Elan3 driver -style clone
958 only). */
njn2335d112005-05-15 20:52:04 +0000959 child->vex.guest_GDT = (HWord)NULL;
sewardj468dc792005-05-31 10:12:06 +0000960
961 if (inherit_parents_GDT && parent->vex.guest_GDT != (HWord)NULL) {
962 child->vex.guest_GDT = (HWord)alloc_zeroed_x86_GDT();
963 copy_GDT_from_to( (VexGuestX86SegDescr*)parent->vex.guest_GDT,
964 (VexGuestX86SegDescr*)child->vex.guest_GDT );
965 }
njn2335d112005-05-15 20:52:04 +0000966}
967
sewardja8d8e232005-06-07 20:04:56 +0000968
njn2335d112005-05-15 20:52:04 +0000969/* ---------------------------------------------------------------------
nethercote8ff888f2004-11-17 17:11:45 +0000970 PRE/POST wrappers for x86/Linux-specific syscalls
971 ------------------------------------------------------------------ */
972
sewardja8d8e232005-06-07 20:04:56 +0000973#define PRE(name) DEFN_PRE_TEMPLATE(x86_linux, name)
974#define POST(name) DEFN_POST_TEMPLATE(x86_linux, name)
nethercote8ff888f2004-11-17 17:11:45 +0000975
sewardja8d8e232005-06-07 20:04:56 +0000976/* Add prototypes for the wrappers declared here, so that gcc doesn't
977 harass us for not having prototypes. Really this is a kludge --
978 the right thing to do is to make these wrappers 'static' since they
979 aren't visible outside this file, but that requires even more macro
980 magic. */
981DECL_TEMPLATE(x86_linux, sys_socketcall);
982DECL_TEMPLATE(x86_linux, sys_stat64);
983DECL_TEMPLATE(x86_linux, sys_fstat64);
984DECL_TEMPLATE(x86_linux, sys_lstat64);
985DECL_TEMPLATE(x86_linux, sys_clone);
986DECL_TEMPLATE(x86_linux, old_mmap);
987DECL_TEMPLATE(x86_linux, sys_sigreturn);
988DECL_TEMPLATE(x86_linux, sys_ipc);
989DECL_TEMPLATE(x86_linux, sys_rt_sigreturn);
990DECL_TEMPLATE(x86_linux, sys_modify_ldt);
sewardjbc22cf72005-06-08 00:02:49 +0000991DECL_TEMPLATE(x86_linux, sys_set_thread_area);
sewardje6d5e722005-06-10 10:27:55 +0000992DECL_TEMPLATE(x86_linux, sys_get_thread_area);
sewardj8c257322005-06-08 01:01:48 +0000993DECL_TEMPLATE(x86_linux, sys_ptrace);
sewardj696c5512005-06-08 23:38:32 +0000994DECL_TEMPLATE(x86_linux, sys_sigaction);
995DECL_TEMPLATE(x86_linux, old_select);
nethercote8ff888f2004-11-17 17:11:45 +0000996
sewardj696c5512005-06-08 23:38:32 +0000997PRE(old_select)
998{
999 /* struct sel_arg_struct {
1000 unsigned long n;
1001 fd_set *inp, *outp, *exp;
1002 struct timeval *tvp;
1003 };
1004 */
1005 PRE_REG_READ1(long, "old_select", struct sel_arg_struct *, args);
1006 PRE_MEM_READ( "old_select(args)", ARG1, 5*sizeof(UWord) );
1007 *flags |= SfMayBlock;
1008 {
1009 UInt* arg_struct = (UInt*)ARG1;
1010 UInt a1, a2, a3, a4, a5;
1011
1012 a1 = arg_struct[0];
1013 a2 = arg_struct[1];
1014 a3 = arg_struct[2];
1015 a4 = arg_struct[3];
1016 a5 = arg_struct[4];
1017
1018 PRINT("old_select ( %d, %p, %p, %p, %p )", a1,a2,a3,a4,a5);
1019 if (a2 != (Addr)NULL)
1020 PRE_MEM_READ( "old_select(readfds)", a2, a1/8 /* __FD_SETSIZE/8 */ );
1021 if (a3 != (Addr)NULL)
1022 PRE_MEM_READ( "old_select(writefds)", a3, a1/8 /* __FD_SETSIZE/8 */ );
1023 if (a4 != (Addr)NULL)
1024 PRE_MEM_READ( "old_select(exceptfds)", a4, a1/8 /* __FD_SETSIZE/8 */ );
1025 if (a5 != (Addr)NULL)
1026 PRE_MEM_READ( "old_select(timeout)", a5, sizeof(struct vki_timeval) );
1027 }
1028}
nethercote3d5e9102004-11-17 18:22:38 +00001029
sewardja8d8e232005-06-07 20:04:56 +00001030PRE(sys_clone)
nethercote3d5e9102004-11-17 18:22:38 +00001031{
sewardjb5f6f512005-03-10 23:59:00 +00001032 UInt cloneflags;
nethercote3d5e9102004-11-17 18:22:38 +00001033
sewardjb5f6f512005-03-10 23:59:00 +00001034 PRINT("sys_clone ( %x, %p, %p, %p, %p )",ARG1,ARG2,ARG3,ARG4,ARG5);
1035 PRE_REG_READ5(int, "clone",
1036 unsigned long, flags,
1037 void *, child_stack,
1038 int *, parent_tidptr,
1039 vki_modify_ldt_t *, tlsinfo,
1040 int *, child_tidptr);
1041
1042 if (ARG1 & VKI_CLONE_PARENT_SETTID) {
1043 PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
1044 if (!VG_(is_addressable)(ARG3, sizeof(Int), VKI_PROT_WRITE)) {
sewardja8d8e232005-06-07 20:04:56 +00001045 SET_STATUS_Failure( VKI_EFAULT );
sewardjb5f6f512005-03-10 23:59:00 +00001046 return;
1047 }
nethercote3d5e9102004-11-17 18:22:38 +00001048 }
sewardjb5f6f512005-03-10 23:59:00 +00001049 if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
1050 PRE_MEM_WRITE("clone(child_tidptr)", ARG5, sizeof(Int));
1051 if (!VG_(is_addressable)(ARG5, sizeof(Int), VKI_PROT_WRITE)) {
sewardja8d8e232005-06-07 20:04:56 +00001052 SET_STATUS_Failure( VKI_EFAULT );
sewardjb5f6f512005-03-10 23:59:00 +00001053 return;
1054 }
1055 }
1056 if (ARG1 & VKI_CLONE_SETTLS) {
1057 PRE_MEM_READ("clone(tls_user_desc)", ARG4, sizeof(vki_modify_ldt_t));
1058 if (!VG_(is_addressable)(ARG4, sizeof(vki_modify_ldt_t), VKI_PROT_READ)) {
sewardja8d8e232005-06-07 20:04:56 +00001059 SET_STATUS_Failure( VKI_EFAULT );
sewardjb5f6f512005-03-10 23:59:00 +00001060 return;
1061 }
1062 }
1063
1064 cloneflags = ARG1;
1065
sewardj7eb7c582005-06-23 01:02:53 +00001066 if (!ML_(client_signal_OK)(ARG1 & VKI_CSIGNAL)) {
sewardja8d8e232005-06-07 20:04:56 +00001067 SET_STATUS_Failure( VKI_EINVAL );
sewardjb5f6f512005-03-10 23:59:00 +00001068 return;
1069 }
1070
sewardj468dc792005-05-31 10:12:06 +00001071 /* Be ultra-paranoid and filter out any clone-variants we don't understand:
1072 - ??? specifies clone flags of 0x100011
1073 - ??? specifies clone flags of 0x1200011.
1074 - NPTL specifies clone flags of 0x7D0F00.
1075 - The Quadrics Elan3 driver specifies clone flags of 0xF00.
1076 Everything else is rejected.
1077 */
sewardj934d2d52005-05-31 13:08:03 +00001078 if (
1079 (cloneflags == 0x100011 || cloneflags == 0x1200011
1080 || cloneflags == 0x7D0F00
sewardja8d8e232005-06-07 20:04:56 +00001081 || cloneflags == 0x790F00
sewardjd15ce0c2005-05-31 21:07:01 +00001082 || cloneflags == 0x3D0F00
sewardj934d2d52005-05-31 13:08:03 +00001083 || cloneflags == 0xF00
1084 || cloneflags == 0xF21)) {
1085 /* OK */
sewardj468dc792005-05-31 10:12:06 +00001086 }
1087 else {
1088 /* Nah. We don't like it. Go away. */
1089 goto reject;
1090 }
1091
sewardjb5f6f512005-03-10 23:59:00 +00001092 /* Only look at the flags we really care about */
sewardja8d8e232005-06-07 20:04:56 +00001093 switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS
1094 | VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
sewardjb5f6f512005-03-10 23:59:00 +00001095 case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
1096 /* thread creation */
sewardja8d8e232005-06-07 20:04:56 +00001097 SET_STATUS_from_SysRes(
1098 do_clone(tid,
1099 ARG1, /* flags */
1100 (Addr)ARG2, /* child ESP */
1101 (Int *)ARG3, /* parent_tidptr */
1102 (Int *)ARG5, /* child_tidptr */
1103 (vki_modify_ldt_t *)ARG4)); /* set_tls */
sewardjb5f6f512005-03-10 23:59:00 +00001104 break;
1105
1106 case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
1107 /* FALLTHROUGH - assume vfork == fork */
1108 cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
1109
1110 case 0: /* plain fork */
sewardja8d8e232005-06-07 20:04:56 +00001111 SET_STATUS_from_SysRes(
1112 do_fork_clone(tid,
sewardje7aa4ae2005-06-09 12:43:42 +00001113 cloneflags, /* flags */
sewardja8d8e232005-06-07 20:04:56 +00001114 (Addr)ARG2, /* child ESP */
1115 (Int *)ARG3, /* parent_tidptr */
1116 (Int *)ARG5)); /* child_tidptr */
sewardjb5f6f512005-03-10 23:59:00 +00001117 break;
1118
1119 default:
sewardj468dc792005-05-31 10:12:06 +00001120 reject:
sewardjb5f6f512005-03-10 23:59:00 +00001121 /* should we just ENOSYS? */
sewardj468dc792005-05-31 10:12:06 +00001122 VG_(message)(Vg_UserMsg, "");
1123 VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%x", ARG1);
1124 VG_(message)(Vg_UserMsg, "");
1125 VG_(message)(Vg_UserMsg, "NOTE: if this happened when attempting "
1126 "to run code using");
1127 VG_(message)(Vg_UserMsg, " Quadrics Elan3 user-space drivers,"
1128 " you should re-run ");
1129 VG_(message)(Vg_UserMsg, " with --support-elan3=yes.");
1130 VG_(message)(Vg_UserMsg, "");
1131 VG_(message)(Vg_UserMsg, "The only supported clone() uses are:");
1132 VG_(message)(Vg_UserMsg, " - via a threads library (LinuxThreads or NPTL)");
1133 VG_(message)(Vg_UserMsg, " - via the implementation of fork or vfork");
1134 VG_(message)(Vg_UserMsg, " - for the Quadrics Elan3 user-space driver");
sewardjb5f6f512005-03-10 23:59:00 +00001135 VG_(unimplemented)
sewardj468dc792005-05-31 10:12:06 +00001136 ("Valgrind does not support general clone().");
sewardjb5f6f512005-03-10 23:59:00 +00001137 }
1138
sewardja8d8e232005-06-07 20:04:56 +00001139 if (SUCCESS) {
sewardjb5f6f512005-03-10 23:59:00 +00001140 if (ARG1 & VKI_CLONE_PARENT_SETTID)
1141 POST_MEM_WRITE(ARG3, sizeof(Int));
1142 if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID))
1143 POST_MEM_WRITE(ARG5, sizeof(Int));
1144
1145 /* Thread creation was successful; let the child have the chance
1146 to run */
sewardja8d8e232005-06-07 20:04:56 +00001147 *flags |= SfYieldAfter;
sewardjb5f6f512005-03-10 23:59:00 +00001148 }
1149}
1150
sewardja8d8e232005-06-07 20:04:56 +00001151PRE(sys_sigreturn)
sewardjb5f6f512005-03-10 23:59:00 +00001152{
sewardja8d8e232005-06-07 20:04:56 +00001153 ThreadState* tst;
sewardjb5f6f512005-03-10 23:59:00 +00001154 PRINT("sigreturn ( )");
1155
sewardja8d8e232005-06-07 20:04:56 +00001156 vg_assert(VG_(is_valid_tid)(tid));
1157 vg_assert(tid >= 1 && tid < VG_N_THREADS);
1158 vg_assert(VG_(is_running_thread)(tid));
1159
sewardjb5f6f512005-03-10 23:59:00 +00001160 /* Adjust esp to point to start of frame; skip back up over
1161 sigreturn sequence's "popl %eax" and handler ret addr */
sewardja8d8e232005-06-07 20:04:56 +00001162 tst = VG_(get_ThreadState)(tid);
sewardjb5f6f512005-03-10 23:59:00 +00001163 tst->arch.vex.guest_ESP -= sizeof(Addr)+sizeof(Word);
1164
1165 /* This is only so that the EIP is (might be) useful to report if
1166 something goes wrong in the sigreturn */
sewardj7eb7c582005-06-23 01:02:53 +00001167 ML_(fixup_guest_state_to_restart_syscall)(&tst->arch);
sewardjb5f6f512005-03-10 23:59:00 +00001168
sewardj985fabb2005-04-24 14:18:14 +00001169 VG_(sigframe_destroy)(tid, False);
sewardjb5f6f512005-03-10 23:59:00 +00001170
sewardja8d8e232005-06-07 20:04:56 +00001171 /* For unclear reasons, it appears we need the syscall to return
1172 without changing %EAX. Since %EAX is the return value, and can
1173 denote either success or failure, we must set up so that the
1174 driver logic copies it back unchanged. Also, note %EAX is of
1175 the guest registers written by VG_(sigframe_destroy). */
cerion85665ca2005-06-20 15:51:07 +00001176 SET_STATUS_from_SysRes( VG_(mk_SysRes_x86_linux)( tst->arch.vex.guest_EAX ) );
sewardjb5f6f512005-03-10 23:59:00 +00001177
sewardja8d8e232005-06-07 20:04:56 +00001178 /* Check to see if some any signals arose as a result of this. */
1179 *flags |= SfPollAfter;
nethercote3d5e9102004-11-17 18:22:38 +00001180}
1181
sewardja8d8e232005-06-07 20:04:56 +00001182PRE(sys_rt_sigreturn)
sewardjd571aff2005-03-15 14:47:30 +00001183{
sewardja8d8e232005-06-07 20:04:56 +00001184 ThreadState* tst;
sewardjd571aff2005-03-15 14:47:30 +00001185 PRINT("rt_sigreturn ( )");
1186
sewardja8d8e232005-06-07 20:04:56 +00001187 vg_assert(VG_(is_valid_tid)(tid));
1188 vg_assert(tid >= 1 && tid < VG_N_THREADS);
1189 vg_assert(VG_(is_running_thread)(tid));
1190
sewardjd571aff2005-03-15 14:47:30 +00001191 /* Adjust esp to point to start of frame; skip back up over handler
1192 ret addr */
sewardja8d8e232005-06-07 20:04:56 +00001193 tst = VG_(get_ThreadState)(tid);
sewardjd571aff2005-03-15 14:47:30 +00001194 tst->arch.vex.guest_ESP -= sizeof(Addr);
1195
1196 /* This is only so that the EIP is (might be) useful to report if
1197 something goes wrong in the sigreturn */
sewardj7eb7c582005-06-23 01:02:53 +00001198 ML_(fixup_guest_state_to_restart_syscall)(&tst->arch);
sewardjd571aff2005-03-15 14:47:30 +00001199
sewardj5bcde922005-05-03 22:31:22 +00001200 VG_(sigframe_destroy)(tid, True);
sewardjd571aff2005-03-15 14:47:30 +00001201
sewardja8d8e232005-06-07 20:04:56 +00001202 /* For unclear reasons, it appears we need the syscall to return
1203 without changing %EAX. Since %EAX is the return value, and can
1204 denote either success or failure, we must set up so that the
1205 driver logic copies it back unchanged. Also, note %EAX is of
1206 the guest registers written by VG_(sigframe_destroy). */
cerion85665ca2005-06-20 15:51:07 +00001207 SET_STATUS_from_SysRes( VG_(mk_SysRes_x86_linux)( tst->arch.vex.guest_EAX ) );
sewardjd571aff2005-03-15 14:47:30 +00001208
sewardja8d8e232005-06-07 20:04:56 +00001209 /* Check to see if some any signals arose as a result of this. */
1210 *flags |= SfPollAfter;
sewardjd571aff2005-03-15 14:47:30 +00001211}
1212
sewardja8d8e232005-06-07 20:04:56 +00001213PRE(sys_modify_ldt)
nethercote8ff888f2004-11-17 17:11:45 +00001214{
njn22cfccb2004-11-27 16:10:23 +00001215 PRINT("sys_modify_ldt ( %d, %p, %d )", ARG1,ARG2,ARG3);
nethercote8ff888f2004-11-17 17:11:45 +00001216 PRE_REG_READ3(int, "modify_ldt", int, func, void *, ptr,
1217 unsigned long, bytecount);
1218
njn22cfccb2004-11-27 16:10:23 +00001219 if (ARG1 == 0) {
nethercote8ff888f2004-11-17 17:11:45 +00001220 /* read the LDT into ptr */
njn22cfccb2004-11-27 16:10:23 +00001221 PRE_MEM_WRITE( "modify_ldt(ptr)", ARG2, ARG3 );
nethercote8ff888f2004-11-17 17:11:45 +00001222 }
njn22cfccb2004-11-27 16:10:23 +00001223 if (ARG1 == 1 || ARG1 == 0x11) {
nethercote8ff888f2004-11-17 17:11:45 +00001224 /* write the LDT with the entry pointed at by ptr */
njn22cfccb2004-11-27 16:10:23 +00001225 PRE_MEM_READ( "modify_ldt(ptr)", ARG2, sizeof(vki_modify_ldt_t) );
nethercote8ff888f2004-11-17 17:11:45 +00001226 }
1227 /* "do" the syscall ourselves; the kernel never sees it */
sewardja8d8e232005-06-07 20:04:56 +00001228 SET_STATUS_from_SysRes( sys_modify_ldt( tid, ARG1, (void*)ARG2, ARG3 ) );
nethercote8ff888f2004-11-17 17:11:45 +00001229
sewardja8d8e232005-06-07 20:04:56 +00001230 if (ARG1 == 0 && SUCCESS && RES > 0) {
njn22cfccb2004-11-27 16:10:23 +00001231 POST_MEM_WRITE( ARG2, RES );
nethercote8ff888f2004-11-17 17:11:45 +00001232 }
1233}
1234
sewardjbc22cf72005-06-08 00:02:49 +00001235PRE(sys_set_thread_area)
1236{
1237 PRINT("sys_set_thread_area ( %p )", ARG1);
1238 PRE_REG_READ1(int, "set_thread_area", struct user_desc *, u_info)
1239 PRE_MEM_READ( "set_thread_area(u_info)", ARG1, sizeof(vki_modify_ldt_t) );
1240
1241 /* "do" the syscall ourselves; the kernel never sees it */
1242 SET_STATUS_from_SysRes( sys_set_thread_area( tid, (void *)ARG1 ) );
1243}
1244
sewardje6d5e722005-06-10 10:27:55 +00001245PRE(sys_get_thread_area)
1246{
1247 PRINT("sys_get_thread_area ( %p )", ARG1);
1248 PRE_REG_READ1(int, "get_thread_area", struct user_desc *, u_info)
1249 PRE_MEM_WRITE( "get_thread_area(u_info)", ARG1, sizeof(vki_modify_ldt_t) );
1250
1251 /* "do" the syscall ourselves; the kernel never sees it */
1252 SET_STATUS_from_SysRes( sys_get_thread_area( tid, (void *)ARG1 ) );
1253
1254 if (SUCCESS) {
1255 POST_MEM_WRITE( ARG1, sizeof(vki_modify_ldt_t) );
1256 }
1257}
sewardj8c257322005-06-08 01:01:48 +00001258
1259// Parts of this are x86-specific, but the *PEEK* cases are generic.
1260// XXX: Why is the memory pointed to by ARG3 never checked?
1261PRE(sys_ptrace)
1262{
1263 PRINT("sys_ptrace ( %d, %d, %p, %p )", ARG1,ARG2,ARG3,ARG4);
1264 PRE_REG_READ4(int, "ptrace",
1265 long, request, long, pid, long, addr, long, data);
1266 switch (ARG1) {
1267 case VKI_PTRACE_PEEKTEXT:
1268 case VKI_PTRACE_PEEKDATA:
1269 case VKI_PTRACE_PEEKUSR:
1270 PRE_MEM_WRITE( "ptrace(peek)", ARG4,
1271 sizeof (long));
1272 break;
1273 case VKI_PTRACE_GETREGS:
1274 PRE_MEM_WRITE( "ptrace(getregs)", ARG4,
1275 sizeof (struct vki_user_regs_struct));
1276 break;
1277 case VKI_PTRACE_GETFPREGS:
1278 PRE_MEM_WRITE( "ptrace(getfpregs)", ARG4,
1279 sizeof (struct vki_user_i387_struct));
1280 break;
1281 case VKI_PTRACE_GETFPXREGS:
1282 PRE_MEM_WRITE( "ptrace(getfpxregs)", ARG4,
1283 sizeof(struct vki_user_fxsr_struct) );
1284 break;
1285 case VKI_PTRACE_SETREGS:
1286 PRE_MEM_READ( "ptrace(setregs)", ARG4,
1287 sizeof (struct vki_user_regs_struct));
1288 break;
1289 case VKI_PTRACE_SETFPREGS:
1290 PRE_MEM_READ( "ptrace(setfpregs)", ARG4,
1291 sizeof (struct vki_user_i387_struct));
1292 break;
1293 case VKI_PTRACE_SETFPXREGS:
1294 PRE_MEM_READ( "ptrace(setfpxregs)", ARG4,
1295 sizeof(struct vki_user_fxsr_struct) );
1296 break;
1297 default:
1298 break;
1299 }
1300}
1301
1302POST(sys_ptrace)
1303{
1304 switch (ARG1) {
1305 case VKI_PTRACE_PEEKTEXT:
1306 case VKI_PTRACE_PEEKDATA:
1307 case VKI_PTRACE_PEEKUSR:
1308 POST_MEM_WRITE( ARG4, sizeof (long));
1309 break;
1310 case VKI_PTRACE_GETREGS:
1311 POST_MEM_WRITE( ARG4, sizeof (struct vki_user_regs_struct));
1312 break;
1313 case VKI_PTRACE_GETFPREGS:
1314 POST_MEM_WRITE( ARG4, sizeof (struct vki_user_i387_struct));
1315 break;
1316 case VKI_PTRACE_GETFPXREGS:
1317 POST_MEM_WRITE( ARG4, sizeof(struct vki_user_fxsr_struct) );
1318 break;
1319 default:
1320 break;
1321 }
1322}
njnca0518d2004-11-26 19:34:36 +00001323
njnb249fd72004-11-29 14:24:57 +00001324static Addr deref_Addr ( ThreadId tid, Addr a, Char* s )
1325{
1326 Addr* a_p = (Addr*)a;
1327 PRE_MEM_READ( s, (Addr)a_p, sizeof(Addr) );
1328 return *a_p;
1329}
njnc6168192004-11-29 13:54:10 +00001330
sewardja8d8e232005-06-07 20:04:56 +00001331PRE(sys_ipc)
njnc6168192004-11-29 13:54:10 +00001332{
1333 PRINT("sys_ipc ( %d, %d, %d, %d, %p, %d )", ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
1334 // XXX: this is simplistic -- some args are not used in all circumstances.
1335 PRE_REG_READ6(int, "ipc",
1336 vki_uint, call, int, first, int, second, int, third,
1337 void *, ptr, long, fifth)
1338
1339 switch (ARG1 /* call */) {
1340 case VKI_SEMOP:
sewardj7eb7c582005-06-23 01:02:53 +00001341 ML_(generic_PRE_sys_semop)( tid, ARG2, ARG5, ARG3 );
sewardja8d8e232005-06-07 20:04:56 +00001342 *flags |= SfMayBlock;
njnc6168192004-11-29 13:54:10 +00001343 break;
1344 case VKI_SEMGET:
1345 break;
1346 case VKI_SEMCTL:
1347 {
sewardjb369c5e2005-03-24 17:52:02 +00001348 UWord arg = deref_Addr( tid, ARG5, "semctl(arg)" );
sewardj7eb7c582005-06-23 01:02:53 +00001349 ML_(generic_PRE_sys_semctl)( tid, ARG2, ARG3, ARG4, arg );
njnc6168192004-11-29 13:54:10 +00001350 break;
1351 }
1352 case VKI_SEMTIMEDOP:
sewardj7eb7c582005-06-23 01:02:53 +00001353 ML_(generic_PRE_sys_semtimedop)( tid, ARG2, ARG5, ARG3, ARG6 );
sewardja8d8e232005-06-07 20:04:56 +00001354 *flags |= SfMayBlock;
njnc6168192004-11-29 13:54:10 +00001355 break;
1356 case VKI_MSGSND:
sewardj7eb7c582005-06-23 01:02:53 +00001357 ML_(generic_PRE_sys_msgsnd)( tid, ARG2, ARG5, ARG3, ARG4 );
sewardja8d8e232005-06-07 20:04:56 +00001358 if ((ARG4 & VKI_IPC_NOWAIT) == 0)
1359 *flags |= SfMayBlock;
njnc6168192004-11-29 13:54:10 +00001360 break;
njnc6168192004-11-29 13:54:10 +00001361 case VKI_MSGRCV:
1362 {
sewardjb369c5e2005-03-24 17:52:02 +00001363 Addr msgp;
1364 Word msgtyp;
njnc6168192004-11-29 13:54:10 +00001365
sewardjb369c5e2005-03-24 17:52:02 +00001366 msgp = deref_Addr( tid,
1367 (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgp),
1368 "msgrcv(msgp)" );
1369 msgtyp = deref_Addr( tid,
1370 (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgtyp),
1371 "msgrcv(msgp)" );
njnc6168192004-11-29 13:54:10 +00001372
sewardj7eb7c582005-06-23 01:02:53 +00001373 ML_(generic_PRE_sys_msgrcv)( tid, ARG2, msgp, ARG3, msgtyp, ARG4 );
njnc6168192004-11-29 13:54:10 +00001374
sewardja8d8e232005-06-07 20:04:56 +00001375 if ((ARG4 & VKI_IPC_NOWAIT) == 0)
1376 *flags |= SfMayBlock;
njnc6168192004-11-29 13:54:10 +00001377 break;
1378 }
1379 case VKI_MSGGET:
1380 break;
1381 case VKI_MSGCTL:
sewardj7eb7c582005-06-23 01:02:53 +00001382 ML_(generic_PRE_sys_msgctl)( tid, ARG2, ARG3, ARG5 );
njnc6168192004-11-29 13:54:10 +00001383 break;
njnc6168192004-11-29 13:54:10 +00001384 case VKI_SHMAT:
sewardja8d8e232005-06-07 20:04:56 +00001385 {
1386 UWord w;
sewardjb369c5e2005-03-24 17:52:02 +00001387 PRE_MEM_WRITE( "shmat(raddr)", ARG4, sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001388 w = ML_(generic_PRE_sys_shmat)( tid, ARG2, ARG5, ARG3 );
sewardja8d8e232005-06-07 20:04:56 +00001389 if (w == 0)
1390 SET_STATUS_Failure( VKI_EINVAL );
1391 else
1392 ARG5 = w;
njnc6168192004-11-29 13:54:10 +00001393 break;
sewardja8d8e232005-06-07 20:04:56 +00001394 }
njnc6168192004-11-29 13:54:10 +00001395 case VKI_SHMDT:
sewardj7eb7c582005-06-23 01:02:53 +00001396 if (!ML_(generic_PRE_sys_shmdt)(tid, ARG5))
sewardja8d8e232005-06-07 20:04:56 +00001397 SET_STATUS_Failure( VKI_EINVAL );
njnc6168192004-11-29 13:54:10 +00001398 break;
1399 case VKI_SHMGET:
1400 break;
1401 case VKI_SHMCTL: /* IPCOP_shmctl */
sewardj7eb7c582005-06-23 01:02:53 +00001402 ML_(generic_PRE_sys_shmctl)( tid, ARG2, ARG3, ARG5 );
njnc6168192004-11-29 13:54:10 +00001403 break;
njnc6168192004-11-29 13:54:10 +00001404 default:
1405 VG_(message)(Vg_DebugMsg, "FATAL: unhandled syscall(ipc) %d", ARG1 );
1406 VG_(core_panic)("... bye!\n");
1407 break; /*NOTREACHED*/
1408 }
1409}
1410
1411POST(sys_ipc)
1412{
sewardja8d8e232005-06-07 20:04:56 +00001413 vg_assert(SUCCESS);
njnc6168192004-11-29 13:54:10 +00001414 switch (ARG1 /* call */) {
1415 case VKI_SEMOP:
1416 case VKI_SEMGET:
1417 break;
1418 case VKI_SEMCTL:
1419 {
sewardjb369c5e2005-03-24 17:52:02 +00001420 UWord arg = deref_Addr( tid, ARG5, "semctl(arg)" );
sewardj7eb7c582005-06-23 01:02:53 +00001421 ML_(generic_PRE_sys_semctl)( tid, ARG2, ARG3, ARG4, arg );
njnc6168192004-11-29 13:54:10 +00001422 break;
1423 }
1424 case VKI_SEMTIMEDOP:
1425 case VKI_MSGSND:
1426 break;
1427 case VKI_MSGRCV:
1428 {
sewardjb369c5e2005-03-24 17:52:02 +00001429 Addr msgp;
1430 Word msgtyp;
1431
1432 msgp = deref_Addr( tid,
1433 (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgp),
1434 "msgrcv(msgp)" );
1435 msgtyp = deref_Addr( tid,
1436 (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgtyp),
1437 "msgrcv(msgp)" );
1438
sewardj7eb7c582005-06-23 01:02:53 +00001439 ML_(generic_POST_sys_msgrcv)( tid, RES, ARG2, msgp, ARG3, msgtyp, ARG4 );
njnc6168192004-11-29 13:54:10 +00001440 break;
1441 }
1442 case VKI_MSGGET:
1443 break;
1444 case VKI_MSGCTL:
sewardj7eb7c582005-06-23 01:02:53 +00001445 ML_(generic_POST_sys_msgctl)( tid, RES, ARG2, ARG3, ARG5 );
njnc6168192004-11-29 13:54:10 +00001446 break;
njnc6168192004-11-29 13:54:10 +00001447 case VKI_SHMAT:
1448 {
njnc6168192004-11-29 13:54:10 +00001449 Addr addr;
1450
1451 /* force readability. before the syscall it is
1452 * indeed uninitialized, as can be seen in
1453 * glibc/sysdeps/unix/sysv/linux/shmat.c */
sewardjb369c5e2005-03-24 17:52:02 +00001454 POST_MEM_WRITE( ARG4, sizeof( Addr ) );
njnc6168192004-11-29 13:54:10 +00001455
1456 addr = deref_Addr ( tid, ARG4, "shmat(addr)" );
1457 if ( addr > 0 ) {
sewardj7eb7c582005-06-23 01:02:53 +00001458 ML_(generic_POST_sys_shmat)( tid, addr, ARG2, ARG5, ARG3 );
njnc6168192004-11-29 13:54:10 +00001459 }
1460 break;
1461 }
1462 case VKI_SHMDT:
sewardj7eb7c582005-06-23 01:02:53 +00001463 ML_(generic_POST_sys_shmdt)( tid, RES, ARG5 );
njnc6168192004-11-29 13:54:10 +00001464 break;
njnc6168192004-11-29 13:54:10 +00001465 case VKI_SHMGET:
1466 break;
1467 case VKI_SHMCTL:
sewardj7eb7c582005-06-23 01:02:53 +00001468 ML_(generic_POST_sys_shmctl)( tid, RES, ARG2, ARG3, ARG5 );
njnc6168192004-11-29 13:54:10 +00001469 break;
njnc6168192004-11-29 13:54:10 +00001470 default:
1471 VG_(message)(Vg_DebugMsg,
1472 "FATAL: unhandled syscall(ipc) %d",
1473 ARG1 );
1474 VG_(core_panic)("... bye!\n");
1475 break; /*NOTREACHED*/
1476 }
1477}
1478
sewardja8d8e232005-06-07 20:04:56 +00001479PRE(old_mmap)
sewardjb5f6f512005-03-10 23:59:00 +00001480{
sewardja8d8e232005-06-07 20:04:56 +00001481 /* struct mmap_arg_struct {
1482 unsigned long addr;
1483 unsigned long len;
1484 unsigned long prot;
1485 unsigned long flags;
1486 unsigned long fd;
1487 unsigned long offset;
1488 }; */
1489 UWord a1, a2, a3, a4, a5, a6;
1490
sewardje6d5e722005-06-10 10:27:55 +00001491 UWord* args = (UWord*)ARG1;
1492 PRE_REG_READ1(long, "old_mmap", struct mmap_arg_struct *, args);
1493 PRE_MEM_READ( "old_mmap(args)", (Addr)args, 6*sizeof(UWord) );
sewardja8d8e232005-06-07 20:04:56 +00001494
sewardje6d5e722005-06-10 10:27:55 +00001495 a1 = args[0];
1496 a2 = args[1];
1497 a3 = args[2];
1498 a4 = args[3];
1499 a5 = args[4];
1500 a6 = args[5];
sewardja8d8e232005-06-07 20:04:56 +00001501
1502 PRINT("old_mmap ( %p, %llu, %d, %d, %d, %d )",
1503 a1, (ULong)a2, a3, a4, a5, a6 );
1504
1505 if (a2 == 0) {
1506 /* SuSV3 says: If len is zero, mmap() shall fail and no mapping
1507 shall be established. */
1508 SET_STATUS_Failure( VKI_EINVAL );
1509 return;
1510 }
1511
1512 if (/*(a4 & VKI_MAP_FIXED) &&*/ (0 != (a1 & (VKI_PAGE_SIZE-1)))) {
1513 /* zap any misaligned addresses. */
1514 SET_STATUS_Failure( VKI_EINVAL );
1515 return;
1516 }
1517
1518 if (a4 & VKI_MAP_FIXED) {
sewardj7eb7c582005-06-23 01:02:53 +00001519 if (!ML_(valid_client_addr)(a1, a2, tid, "old_mmap")) {
sewardja8d8e232005-06-07 20:04:56 +00001520 PRINT("old_mmap failing: %p-%p\n", a1, a1+a2);
1521 SET_STATUS_Failure( VKI_ENOMEM );
1522 }
1523 } else {
1524 Addr a = VG_(find_map_space)(a1, a2, True);
1525 if (0) VG_(printf)("find_map_space(%p, %d) -> %p\n",a1,a2,a);
1526 if (a == 0 && a1 != 0) {
1527 a1 = VG_(find_map_space)(0, a2, True);
1528 }
1529 else
1530 a1 = a;
1531 if (a1 == 0)
1532 SET_STATUS_Failure( VKI_ENOMEM );
1533 else
1534 a4 |= VKI_MAP_FIXED;
1535 }
1536
1537 if (! FAILURE) {
1538 SysRes res = VG_(mmap_native)((void*)a1, a2, a3, a4, a5, a6);
1539 SET_STATUS_from_SysRes(res);
1540 if (!res.isError) {
sewardj7eb7c582005-06-23 01:02:53 +00001541 vg_assert(ML_(valid_client_addr)(res.val, a2, tid, "old_mmap"));
1542 ML_(mmap_segment)( (Addr)res.val, a2, a3, a4, a5, a6 );
sewardja8d8e232005-06-07 20:04:56 +00001543 }
1544 }
1545
1546 if (0)
1547 VG_(printf)("old_mmap( %p, fixed %d ) -> %s(%p)\n",
sewardje6d5e722005-06-10 10:27:55 +00001548 args[0],
1549 args[3]&VKI_MAP_FIXED,
sewardja8d8e232005-06-07 20:04:56 +00001550 FAILURE ? "Fail" : "Success", RES_unchecked);
1551
1552 /* Stay sane */
sewardje6d5e722005-06-10 10:27:55 +00001553 if (SUCCESS && (args[3] & VKI_MAP_FIXED))
1554 vg_assert(RES == args[0]);
sewardjb5f6f512005-03-10 23:59:00 +00001555}
sewardja8d8e232005-06-07 20:04:56 +00001556
1557// XXX: lstat64/fstat64/stat64 are generic, but not necessarily
1558// applicable to every architecture -- I think only to 32-bit archs.
1559// We're going to need something like linux/core_os32.h for such
1560// things, eventually, I think. --njn
1561PRE(sys_lstat64)
njnc6168192004-11-29 13:54:10 +00001562{
sewardja8d8e232005-06-07 20:04:56 +00001563 PRINT("sys_lstat64 ( %p(%s), %p )",ARG1,ARG1,ARG2);
1564 PRE_REG_READ2(long, "lstat64", char *, file_name, struct stat64 *, buf);
1565 PRE_MEM_RASCIIZ( "lstat64(file_name)", ARG1 );
1566 PRE_MEM_WRITE( "lstat64(buf)", ARG2, sizeof(struct vki_stat64) );
1567}
sewardjb5f6f512005-03-10 23:59:00 +00001568
sewardja8d8e232005-06-07 20:04:56 +00001569POST(sys_lstat64)
1570{
1571 vg_assert(SUCCESS);
1572 if (RES == 0) {
1573 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
sewardjb5f6f512005-03-10 23:59:00 +00001574 }
njnc6168192004-11-29 13:54:10 +00001575}
1576
sewardja8d8e232005-06-07 20:04:56 +00001577PRE(sys_stat64)
njnc6168192004-11-29 13:54:10 +00001578{
sewardja8d8e232005-06-07 20:04:56 +00001579 PRINT("sys_stat64 ( %p, %p )",ARG1,ARG2);
1580 PRE_REG_READ2(long, "stat64", char *, file_name, struct stat64 *, buf);
1581 PRE_MEM_RASCIIZ( "stat64(file_name)", ARG1 );
1582 PRE_MEM_WRITE( "stat64(buf)", ARG2, sizeof(struct vki_stat64) );
njnc6168192004-11-29 13:54:10 +00001583}
1584
sewardja8d8e232005-06-07 20:04:56 +00001585POST(sys_stat64)
1586{
1587 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
1588}
1589
1590PRE(sys_fstat64)
1591{
1592 PRINT("sys_fstat64 ( %d, %p )",ARG1,ARG2);
1593 PRE_REG_READ2(long, "fstat64", unsigned long, fd, struct stat64 *, buf);
1594 PRE_MEM_WRITE( "fstat64(buf)", ARG2, sizeof(struct vki_stat64) );
1595}
1596
1597POST(sys_fstat64)
1598{
1599 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
1600}
1601
1602PRE(sys_socketcall)
1603{
1604# define ARG2_0 (((UWord*)ARG2)[0])
1605# define ARG2_1 (((UWord*)ARG2)[1])
1606# define ARG2_2 (((UWord*)ARG2)[2])
1607# define ARG2_3 (((UWord*)ARG2)[3])
1608# define ARG2_4 (((UWord*)ARG2)[4])
1609# define ARG2_5 (((UWord*)ARG2)[5])
1610
1611 *flags |= SfMayBlock;
1612 PRINT("sys_socketcall ( %d, %p )",ARG1,ARG2);
1613 PRE_REG_READ2(long, "socketcall", int, call, unsigned long *, args);
1614
1615 switch (ARG1 /* request */) {
1616
1617 case VKI_SYS_SOCKETPAIR:
1618 /* int socketpair(int d, int type, int protocol, int sv[2]); */
1619 PRE_MEM_READ( "socketcall.socketpair(args)", ARG2, 4*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001620 ML_(generic_PRE_sys_socketpair)( tid, ARG2_0, ARG2_1, ARG2_2, ARG2_3 );
sewardja8d8e232005-06-07 20:04:56 +00001621 break;
1622
1623 case VKI_SYS_SOCKET:
1624 /* int socket(int domain, int type, int protocol); */
1625 PRE_MEM_READ( "socketcall.socket(args)", ARG2, 3*sizeof(Addr) );
1626 break;
1627
1628 case VKI_SYS_BIND:
1629 /* int bind(int sockfd, struct sockaddr *my_addr,
1630 int addrlen); */
1631 PRE_MEM_READ( "socketcall.bind(args)", ARG2, 3*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001632 ML_(generic_PRE_sys_bind)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001633 break;
1634
1635 case VKI_SYS_LISTEN:
1636 /* int listen(int s, int backlog); */
1637 PRE_MEM_READ( "socketcall.listen(args)", ARG2, 2*sizeof(Addr) );
1638 break;
1639
1640 case VKI_SYS_ACCEPT: {
1641 /* int accept(int s, struct sockaddr *addr, int *addrlen); */
1642 PRE_MEM_READ( "socketcall.accept(args)", ARG2, 3*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001643 ML_(generic_PRE_sys_accept)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001644 break;
1645 }
1646
1647 case VKI_SYS_SENDTO:
1648 /* int sendto(int s, const void *msg, int len,
1649 unsigned int flags,
1650 const struct sockaddr *to, int tolen); */
1651 PRE_MEM_READ( "socketcall.sendto(args)", ARG2, 6*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001652 ML_(generic_PRE_sys_sendto)( tid, ARG2_0, ARG2_1, ARG2_2,
sewardja8d8e232005-06-07 20:04:56 +00001653 ARG2_3, ARG2_4, ARG2_5 );
1654 break;
1655
1656 case VKI_SYS_SEND:
1657 /* int send(int s, const void *msg, size_t len, int flags); */
1658 PRE_MEM_READ( "socketcall.send(args)", ARG2, 4*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001659 ML_(generic_PRE_sys_send)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001660 break;
1661
1662 case VKI_SYS_RECVFROM:
1663 /* int recvfrom(int s, void *buf, int len, unsigned int flags,
1664 struct sockaddr *from, int *fromlen); */
1665 PRE_MEM_READ( "socketcall.recvfrom(args)", ARG2, 6*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001666 ML_(generic_PRE_sys_recvfrom)( tid, ARG2_0, ARG2_1, ARG2_2,
sewardja8d8e232005-06-07 20:04:56 +00001667 ARG2_3, ARG2_4, ARG2_5 );
1668 break;
1669
1670 case VKI_SYS_RECV:
1671 /* int recv(int s, void *buf, int len, unsigned int flags); */
1672 /* man 2 recv says:
1673 The recv call is normally used only on a connected socket
1674 (see connect(2)) and is identical to recvfrom with a NULL
1675 from parameter.
1676 */
1677 PRE_MEM_READ( "socketcall.recv(args)", ARG2, 4*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001678 ML_(generic_PRE_sys_recv)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001679 break;
1680
1681 case VKI_SYS_CONNECT:
1682 /* int connect(int sockfd,
1683 struct sockaddr *serv_addr, int addrlen ); */
1684 PRE_MEM_READ( "socketcall.connect(args)", ARG2, 3*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001685 ML_(generic_PRE_sys_connect)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001686 break;
1687
1688 case VKI_SYS_SETSOCKOPT:
1689 /* int setsockopt(int s, int level, int optname,
1690 const void *optval, int optlen); */
1691 PRE_MEM_READ( "socketcall.setsockopt(args)", ARG2, 5*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001692 ML_(generic_PRE_sys_setsockopt)( tid, ARG2_0, ARG2_1, ARG2_2,
sewardja8d8e232005-06-07 20:04:56 +00001693 ARG2_3, ARG2_4 );
1694 break;
1695
1696 case VKI_SYS_GETSOCKOPT:
1697 /* int getsockopt(int s, int level, int optname,
1698 void *optval, socklen_t *optlen); */
1699 PRE_MEM_READ( "socketcall.getsockopt(args)", ARG2, 5*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001700 ML_(generic_PRE_sys_getsockopt)( tid, ARG2_0, ARG2_1, ARG2_2,
sewardja8d8e232005-06-07 20:04:56 +00001701 ARG2_3, ARG2_4 );
1702 break;
1703
1704 case VKI_SYS_GETSOCKNAME:
1705 /* int getsockname(int s, struct sockaddr* name, int* namelen) */
1706 PRE_MEM_READ( "socketcall.getsockname(args)", ARG2, 3*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001707 ML_(generic_PRE_sys_getsockname)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001708 break;
1709
1710 case VKI_SYS_GETPEERNAME:
1711 /* int getpeername(int s, struct sockaddr* name, int* namelen) */
1712 PRE_MEM_READ( "socketcall.getpeername(args)", ARG2, 3*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001713 ML_(generic_PRE_sys_getpeername)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001714 break;
1715
1716 case VKI_SYS_SHUTDOWN:
1717 /* int shutdown(int s, int how); */
1718 PRE_MEM_READ( "socketcall.shutdown(args)", ARG2, 2*sizeof(Addr) );
1719 break;
1720
1721 case VKI_SYS_SENDMSG: {
1722 /* int sendmsg(int s, const struct msghdr *msg, int flags); */
1723
1724 /* this causes warnings, and I don't get why. glibc bug?
1725 * (after all it's glibc providing the arguments array)
1726 PRE_MEM_READ( "socketcall.sendmsg(args)", ARG2, 3*sizeof(Addr) );
1727 */
sewardj7eb7c582005-06-23 01:02:53 +00001728 ML_(generic_PRE_sys_sendmsg)( tid, ARG2_0, ARG2_1 );
sewardja8d8e232005-06-07 20:04:56 +00001729 break;
1730 }
1731
1732 case VKI_SYS_RECVMSG: {
1733 /* int recvmsg(int s, struct msghdr *msg, int flags); */
1734
1735 /* this causes warnings, and I don't get why. glibc bug?
1736 * (after all it's glibc providing the arguments array)
1737 PRE_MEM_READ("socketcall.recvmsg(args)", ARG2, 3*sizeof(Addr) );
1738 */
sewardj7eb7c582005-06-23 01:02:53 +00001739 ML_(generic_PRE_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
sewardja8d8e232005-06-07 20:04:56 +00001740 break;
1741 }
1742
1743 default:
1744 VG_(message)(Vg_DebugMsg,"Warning: unhandled socketcall 0x%x",ARG1);
1745 SET_STATUS_Failure( VKI_EINVAL );
1746 break;
1747 }
1748# undef ARG2_0
1749# undef ARG2_1
1750# undef ARG2_2
1751# undef ARG2_3
1752# undef ARG2_4
1753# undef ARG2_5
1754}
1755
1756POST(sys_socketcall)
1757{
1758# define ARG2_0 (((UWord*)ARG2)[0])
1759# define ARG2_1 (((UWord*)ARG2)[1])
1760# define ARG2_2 (((UWord*)ARG2)[2])
1761# define ARG2_3 (((UWord*)ARG2)[3])
1762# define ARG2_4 (((UWord*)ARG2)[4])
1763# define ARG2_5 (((UWord*)ARG2)[5])
1764
1765 SysRes r;
1766 vg_assert(SUCCESS);
1767 switch (ARG1 /* request */) {
1768
1769 case VKI_SYS_SOCKETPAIR:
sewardj7eb7c582005-06-23 01:02:53 +00001770 r = ML_(generic_POST_sys_socketpair)(
sewardja8d8e232005-06-07 20:04:56 +00001771 tid, VG_(mk_SysRes_Success)(RES),
1772 ARG2_0, ARG2_1, ARG2_2, ARG2_3
1773 );
1774 SET_STATUS_from_SysRes(r);
1775 break;
1776
1777 case VKI_SYS_SOCKET:
sewardj7eb7c582005-06-23 01:02:53 +00001778 r = ML_(generic_POST_sys_socket)( tid, VG_(mk_SysRes_Success)(RES) );
sewardja8d8e232005-06-07 20:04:56 +00001779 SET_STATUS_from_SysRes(r);
1780 break;
1781
1782 case VKI_SYS_BIND:
1783 /* int bind(int sockfd, struct sockaddr *my_addr,
1784 int addrlen); */
1785 break;
1786
1787 case VKI_SYS_LISTEN:
1788 /* int listen(int s, int backlog); */
1789 break;
1790
1791 case VKI_SYS_ACCEPT:
1792 /* int accept(int s, struct sockaddr *addr, int *addrlen); */
sewardj7eb7c582005-06-23 01:02:53 +00001793 r = ML_(generic_POST_sys_accept)( tid, VG_(mk_SysRes_Success)(RES),
sewardja8d8e232005-06-07 20:04:56 +00001794 ARG2_0, ARG2_1, ARG2_2 );
1795 SET_STATUS_from_SysRes(r);
1796 break;
1797
1798 case VKI_SYS_SENDTO:
1799 break;
1800
1801 case VKI_SYS_SEND:
1802 break;
1803
1804 case VKI_SYS_RECVFROM:
sewardj7eb7c582005-06-23 01:02:53 +00001805 ML_(generic_POST_sys_recvfrom)( tid, VG_(mk_SysRes_Success)(RES),
sewardja8d8e232005-06-07 20:04:56 +00001806 ARG2_0, ARG2_1, ARG2_2,
1807 ARG2_3, ARG2_4, ARG2_5 );
1808 break;
1809
1810 case VKI_SYS_RECV:
sewardj7eb7c582005-06-23 01:02:53 +00001811 ML_(generic_POST_sys_recv)( tid, RES, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001812 break;
1813
1814 case VKI_SYS_CONNECT:
1815 break;
1816
1817 case VKI_SYS_SETSOCKOPT:
1818 break;
1819
1820 case VKI_SYS_GETSOCKOPT:
sewardj7eb7c582005-06-23 01:02:53 +00001821 ML_(generic_POST_sys_getsockopt)( tid, VG_(mk_SysRes_Success)(RES),
sewardja8d8e232005-06-07 20:04:56 +00001822 ARG2_0, ARG2_1,
1823 ARG2_2, ARG2_3, ARG2_4 );
1824 break;
1825
1826 case VKI_SYS_GETSOCKNAME:
sewardj7eb7c582005-06-23 01:02:53 +00001827 ML_(generic_POST_sys_getsockname)( tid, VG_(mk_SysRes_Success)(RES),
sewardja8d8e232005-06-07 20:04:56 +00001828 ARG2_0, ARG2_1, ARG2_2 );
1829 break;
1830
1831 case VKI_SYS_GETPEERNAME:
sewardj7eb7c582005-06-23 01:02:53 +00001832 ML_(generic_POST_sys_getpeername)( tid, VG_(mk_SysRes_Success)(RES),
sewardja8d8e232005-06-07 20:04:56 +00001833 ARG2_0, ARG2_1, ARG2_2 );
1834 break;
1835
1836 case VKI_SYS_SHUTDOWN:
1837 break;
1838
1839 case VKI_SYS_SENDMSG:
1840 break;
1841
1842 case VKI_SYS_RECVMSG:
sewardj7eb7c582005-06-23 01:02:53 +00001843 ML_(generic_POST_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
sewardja8d8e232005-06-07 20:04:56 +00001844 break;
1845
1846 default:
1847 VG_(message)(Vg_DebugMsg,"FATAL: unhandled socketcall 0x%x",ARG1);
1848 VG_(core_panic)("... bye!\n");
1849 break; /*NOTREACHED*/
1850 }
1851# undef ARG2_0
1852# undef ARG2_1
1853# undef ARG2_2
1854# undef ARG2_3
1855# undef ARG2_4
1856# undef ARG2_5
1857}
1858
sewardj696c5512005-06-08 23:38:32 +00001859/* Convert from non-RT to RT sigset_t's */
1860static
1861void convert_sigset_to_rt(const vki_old_sigset_t *oldset, vki_sigset_t *set)
1862{
1863 VG_(sigemptyset)(set);
1864 set->sig[0] = *oldset;
1865}
1866PRE(sys_sigaction)
1867{
1868 struct vki_sigaction new, old;
1869 struct vki_sigaction *newp, *oldp;
1870
1871 PRINT("sys_sigaction ( %d, %p, %p )", ARG1,ARG2,ARG3);
1872 PRE_REG_READ3(int, "sigaction",
1873 int, signum, const struct old_sigaction *, act,
1874 struct old_sigaction *, oldact);
1875
1876 newp = oldp = NULL;
1877
1878 if (ARG2 != 0)
1879 PRE_MEM_READ( "sigaction(act)", ARG2, sizeof(struct vki_old_sigaction));
1880
1881 if (ARG3 != 0) {
1882 PRE_MEM_WRITE( "sigaction(oldact)", ARG3, sizeof(struct vki_old_sigaction));
1883 oldp = &old;
1884 }
1885
1886 //jrs 20050207: what?! how can this make any sense?
1887 //if (VG_(is_kerror)(SYSRES))
1888 // return;
1889
1890 if (ARG2 != 0) {
1891 struct vki_old_sigaction *oldnew = (struct vki_old_sigaction *)ARG2;
1892
1893 new.ksa_handler = oldnew->ksa_handler;
1894 new.sa_flags = oldnew->sa_flags;
1895 new.sa_restorer = oldnew->sa_restorer;
1896 convert_sigset_to_rt(&oldnew->sa_mask, &new.sa_mask);
1897 newp = &new;
1898 }
1899
1900 SET_STATUS_from_SysRes( VG_(do_sys_sigaction)(ARG1, newp, oldp) );
1901
1902 if (ARG3 != 0 && SUCCESS && RES == 0) {
1903 struct vki_old_sigaction *oldold = (struct vki_old_sigaction *)ARG3;
1904
1905 oldold->ksa_handler = oldp->ksa_handler;
1906 oldold->sa_flags = oldp->sa_flags;
1907 oldold->sa_restorer = oldp->sa_restorer;
1908 oldold->sa_mask = oldp->sa_mask.sig[0];
1909 }
1910}
1911
1912POST(sys_sigaction)
1913{
1914 vg_assert(SUCCESS);
1915 if (RES == 0 && ARG3 != 0)
1916 POST_MEM_WRITE( ARG3, sizeof(struct vki_old_sigaction));
1917}
1918
1919#undef PRE
1920#undef POST
1921
nethercote8ff888f2004-11-17 17:11:45 +00001922
1923/* ---------------------------------------------------------------------
1924 The x86/Linux syscall table
1925 ------------------------------------------------------------------ */
1926
sewardje7aa4ae2005-06-09 12:43:42 +00001927/* Add an x86-linux specific wrapper to a syscall table. */
sewardja8d8e232005-06-07 20:04:56 +00001928#define PLAX_(sysno, name) WRAPPER_ENTRY_X_(x86_linux, sysno, name)
1929#define PLAXY(sysno, name) WRAPPER_ENTRY_XY(x86_linux, sysno, name)
1930
nethercote8ff888f2004-11-17 17:11:45 +00001931
nethercote3d5e9102004-11-17 18:22:38 +00001932// This table maps from __NR_xxx syscall numbers (from
1933// linux/include/asm-i386/unistd.h) to the appropriate PRE/POST sys_foo()
1934// wrappers on x86 (as per sys_call_table in linux/arch/i386/kernel/entry.S).
1935//
1936// For those syscalls not handled by Valgrind, the annotation indicate its
1937// arch/OS combination, eg. */* (generic), */Linux (Linux only), ?/?
1938// (unknown).
1939
njnaf839f52005-06-23 03:27:57 +00001940const SyscallTableEntry ML_(syscall_table)[] = {
sewardja8d8e232005-06-07 20:04:56 +00001941//zz // (restart_syscall) // 0
nethercote8ff888f2004-11-17 17:11:45 +00001942 GENX_(__NR_exit, sys_exit), // 1
sewardjb5f6f512005-03-10 23:59:00 +00001943 GENX_(__NR_fork, sys_fork), // 2
nethercote8ff888f2004-11-17 17:11:45 +00001944 GENXY(__NR_read, sys_read), // 3
1945 GENX_(__NR_write, sys_write), // 4
1946
1947 GENXY(__NR_open, sys_open), // 5
1948 GENXY(__NR_close, sys_close), // 6
1949 GENXY(__NR_waitpid, sys_waitpid), // 7
1950 GENXY(__NR_creat, sys_creat), // 8
1951 GENX_(__NR_link, sys_link), // 9
1952
1953 GENX_(__NR_unlink, sys_unlink), // 10
nethercote3d5e9102004-11-17 18:22:38 +00001954 GENX_(__NR_execve, sys_execve), // 11
nethercote8ff888f2004-11-17 17:11:45 +00001955 GENX_(__NR_chdir, sys_chdir), // 12
1956 GENXY(__NR_time, sys_time), // 13
1957 GENX_(__NR_mknod, sys_mknod), // 14
1958
1959 GENX_(__NR_chmod, sys_chmod), // 15
sewardja8d8e232005-06-07 20:04:56 +00001960//zz // (__NR_lchown, sys_lchown16), // 16 ## P
nethercote3d5e9102004-11-17 18:22:38 +00001961 GENX_(__NR_break, sys_ni_syscall), // 17
sewardja8d8e232005-06-07 20:04:56 +00001962//zz // (__NR_oldstat, sys_stat), // 18 (obsolete)
nethercote8ff888f2004-11-17 17:11:45 +00001963 GENX_(__NR_lseek, sys_lseek), // 19
1964
1965 GENX_(__NR_getpid, sys_getpid), // 20
1966 LINX_(__NR_mount, sys_mount), // 21
1967 LINX_(__NR_umount, sys_oldumount), // 22
1968 GENX_(__NR_setuid, sys_setuid16), // 23 ## P
1969 GENX_(__NR_getuid, sys_getuid16), // 24 ## P
sewardja8d8e232005-06-07 20:04:56 +00001970//zz
1971//zz // (__NR_stime, sys_stime), // 25 * (SVr4,SVID,X/OPEN)
sewardj8c257322005-06-08 01:01:48 +00001972 PLAXY(__NR_ptrace, sys_ptrace), // 26
nethercote3d5e9102004-11-17 18:22:38 +00001973 GENX_(__NR_alarm, sys_alarm), // 27
sewardja8d8e232005-06-07 20:04:56 +00001974//zz // (__NR_oldfstat, sys_fstat), // 28 * L -- obsolete
nethercote3d5e9102004-11-17 18:22:38 +00001975 GENX_(__NR_pause, sys_pause), // 29
sewardj8c9ea4e2005-06-08 10:46:56 +00001976
1977 GENX_(__NR_utime, sys_utime), // 30
nethercote3d5e9102004-11-17 18:22:38 +00001978 GENX_(__NR_stty, sys_ni_syscall), // 31
1979 GENX_(__NR_gtty, sys_ni_syscall), // 32
1980 GENX_(__NR_access, sys_access), // 33
sewardj8c9ea4e2005-06-08 10:46:56 +00001981 GENX_(__NR_nice, sys_nice), // 34
1982
nethercote3d5e9102004-11-17 18:22:38 +00001983 GENX_(__NR_ftime, sys_ni_syscall), // 35
sewardj8c9ea4e2005-06-08 10:46:56 +00001984 GENX_(__NR_sync, sys_sync), // 36
njn03f1e582005-03-26 20:08:06 +00001985 GENX_(__NR_kill, sys_kill), // 37
nethercote8ff888f2004-11-17 17:11:45 +00001986 GENX_(__NR_rename, sys_rename), // 38
1987 GENX_(__NR_mkdir, sys_mkdir), // 39
sewardj78b50e42005-06-08 01:47:28 +00001988
1989 GENX_(__NR_rmdir, sys_rmdir), // 40
nethercote8ff888f2004-11-17 17:11:45 +00001990 GENXY(__NR_dup, sys_dup), // 41
nethercote3d5e9102004-11-17 18:22:38 +00001991 GENXY(__NR_pipe, sys_pipe), // 42
sewardj78b50e42005-06-08 01:47:28 +00001992 GENXY(__NR_times, sys_times), // 43
nethercote3d5e9102004-11-17 18:22:38 +00001993 GENX_(__NR_prof, sys_ni_syscall), // 44
sewardja8d8e232005-06-07 20:04:56 +00001994//zz
nethercote3d5e9102004-11-17 18:22:38 +00001995 GENX_(__NR_brk, sys_brk), // 45
sewardj8c9ea4e2005-06-08 10:46:56 +00001996 GENX_(__NR_setgid, sys_setgid16), // 46
1997 GENX_(__NR_getgid, sys_getgid16), // 47
sewardja8d8e232005-06-07 20:04:56 +00001998//zz // (__NR_signal, sys_signal), // 48 */* (ANSI C)
nethercote3d5e9102004-11-17 18:22:38 +00001999 GENX_(__NR_geteuid, sys_geteuid16), // 49
sewardj696c5512005-06-08 23:38:32 +00002000
2001 GENX_(__NR_getegid, sys_getegid16), // 50
2002 GENX_(__NR_acct, sys_acct), // 51
2003 LINX_(__NR_umount2, sys_umount), // 52
nethercote3d5e9102004-11-17 18:22:38 +00002004 GENX_(__NR_lock, sys_ni_syscall), // 53
2005 GENXY(__NR_ioctl, sys_ioctl), // 54
sewardj696c5512005-06-08 23:38:32 +00002006
2007 GENXY(__NR_fcntl, sys_fcntl), // 55
nethercote3d5e9102004-11-17 18:22:38 +00002008 GENX_(__NR_mpx, sys_ni_syscall), // 56
sewardj696c5512005-06-08 23:38:32 +00002009 GENX_(__NR_setpgid, sys_setpgid), // 57
nethercote3d5e9102004-11-17 18:22:38 +00002010 GENX_(__NR_ulimit, sys_ni_syscall), // 58
sewardja8d8e232005-06-07 20:04:56 +00002011//zz // (__NR_oldolduname, sys_olduname), // 59 Linux -- obsolete
2012//zz
sewardj78b50e42005-06-08 01:47:28 +00002013 GENX_(__NR_umask, sys_umask), // 60
sewardj696c5512005-06-08 23:38:32 +00002014 GENX_(__NR_chroot, sys_chroot), // 61
sewardja8d8e232005-06-07 20:04:56 +00002015//zz // (__NR_ustat, sys_ustat) // 62 SVr4 -- deprecated
nethercote8ff888f2004-11-17 17:11:45 +00002016 GENXY(__NR_dup2, sys_dup2), // 63
sewardj1d887112005-05-30 21:44:08 +00002017 GENX_(__NR_getppid, sys_getppid), // 64
sewardj78b50e42005-06-08 01:47:28 +00002018
2019 GENX_(__NR_getpgrp, sys_getpgrp), // 65
sewardj696c5512005-06-08 23:38:32 +00002020 GENX_(__NR_setsid, sys_setsid), // 66
2021 PLAXY(__NR_sigaction, sys_sigaction), // 67
sewardja8d8e232005-06-07 20:04:56 +00002022//zz // (__NR_sgetmask, sys_sgetmask), // 68 */* (ANSI C)
2023//zz // (__NR_ssetmask, sys_ssetmask), // 69 */* (ANSI C)
2024//zz
sewardj696c5512005-06-08 23:38:32 +00002025 GENX_(__NR_setreuid, sys_setreuid16), // 70
2026 GENX_(__NR_setregid, sys_setregid16), // 71
sewardja8d8e232005-06-07 20:04:56 +00002027//zz GENX_(__NR_sigsuspend, sys_sigsuspend), // 72
sewardj696c5512005-06-08 23:38:32 +00002028 GENXY(__NR_sigpending, sys_sigpending), // 73
sewardja8d8e232005-06-07 20:04:56 +00002029//zz // (__NR_sethostname, sys_sethostname), // 74 */*
2030//zz
nethercote3d5e9102004-11-17 18:22:38 +00002031 GENX_(__NR_setrlimit, sys_setrlimit), // 75
sewardj696c5512005-06-08 23:38:32 +00002032 GENXY(__NR_getrlimit, sys_old_getrlimit), // 76
2033 GENXY(__NR_getrusage, sys_getrusage), // 77
nethercote3d5e9102004-11-17 18:22:38 +00002034 GENXY(__NR_gettimeofday, sys_gettimeofday), // 78
sewardj696c5512005-06-08 23:38:32 +00002035 GENX_(__NR_settimeofday, sys_settimeofday), // 79
2036
2037 GENXY(__NR_getgroups, sys_getgroups16), // 80
2038 GENX_(__NR_setgroups, sys_setgroups16), // 81
2039 PLAX_(__NR_select, old_select), // 82
sewardj78b50e42005-06-08 01:47:28 +00002040 GENX_(__NR_symlink, sys_symlink), // 83
sewardja8d8e232005-06-07 20:04:56 +00002041//zz // (__NR_oldlstat, sys_lstat), // 84 -- obsolete
2042//zz
rjwalsh17d85302004-11-18 22:56:09 +00002043 GENX_(__NR_readlink, sys_readlink), // 85
sewardja8d8e232005-06-07 20:04:56 +00002044//zz // (__NR_uselib, sys_uselib), // 86 */Linux
2045//zz // (__NR_swapon, sys_swapon), // 87 */Linux
2046//zz // (__NR_reboot, sys_reboot), // 88 */Linux
2047//zz // (__NR_readdir, old_readdir), // 89 -- superseded
2048//zz
2049 PLAX_(__NR_mmap, old_mmap), // 90
nethercote8ff888f2004-11-17 17:11:45 +00002050 GENXY(__NR_munmap, sys_munmap), // 91
sewardj696c5512005-06-08 23:38:32 +00002051 GENX_(__NR_truncate, sys_truncate), // 92
sewardj8c257322005-06-08 01:01:48 +00002052 GENX_(__NR_ftruncate, sys_ftruncate), // 93
sewardj696c5512005-06-08 23:38:32 +00002053 GENX_(__NR_fchmod, sys_fchmod), // 94
2054
2055 GENX_(__NR_fchown, sys_fchown16), // 95
2056 GENX_(__NR_getpriority, sys_getpriority), // 96
2057 GENX_(__NR_setpriority, sys_setpriority), // 97
nethercote3d5e9102004-11-17 18:22:38 +00002058 GENX_(__NR_profil, sys_ni_syscall), // 98
sewardj696c5512005-06-08 23:38:32 +00002059 GENXY(__NR_statfs, sys_statfs), // 99
2060
2061 GENXY(__NR_fstatfs, sys_fstatfs), // 100
2062 LINX_(__NR_ioperm, sys_ioperm), // 101
sewardja8d8e232005-06-07 20:04:56 +00002063 PLAXY(__NR_socketcall, sys_socketcall), // 102 x86/Linux-only
sewardj696c5512005-06-08 23:38:32 +00002064 LINXY(__NR_syslog, sys_syslog), // 103
2065 GENXY(__NR_setitimer, sys_setitimer), // 104
2066
2067 GENXY(__NR_getitimer, sys_getitimer), // 105
2068 GENXY(__NR_stat, sys_newstat), // 106
2069 GENXY(__NR_lstat, sys_newlstat), // 107
2070 GENXY(__NR_fstat, sys_newfstat), // 108
sewardja8d8e232005-06-07 20:04:56 +00002071//zz // (__NR_olduname, sys_uname), // 109 -- obsolete
2072//zz
sewardj696c5512005-06-08 23:38:32 +00002073 GENX_(__NR_iopl, sys_iopl), // 110
2074 LINX_(__NR_vhangup, sys_vhangup), // 111
nethercote3d5e9102004-11-17 18:22:38 +00002075 GENX_(__NR_idle, sys_ni_syscall), // 112
sewardja8d8e232005-06-07 20:04:56 +00002076//zz // (__NR_vm86old, sys_vm86old), // 113 x86/Linux-only
nethercote3d5e9102004-11-17 18:22:38 +00002077 GENXY(__NR_wait4, sys_wait4), // 114
sewardja8d8e232005-06-07 20:04:56 +00002078//zz
2079//zz // (__NR_swapoff, sys_swapoff), // 115 */Linux
sewardj696c5512005-06-08 23:38:32 +00002080 LINXY(__NR_sysinfo, sys_sysinfo), // 116
njnc6168192004-11-29 13:54:10 +00002081 PLAXY(__NR_ipc, sys_ipc), // 117
sewardj78b50e42005-06-08 01:47:28 +00002082 GENX_(__NR_fsync, sys_fsync), // 118
sewardjb5f6f512005-03-10 23:59:00 +00002083 PLAX_(__NR_sigreturn, sys_sigreturn), // 119 ?/Linux
nethercote8ff888f2004-11-17 17:11:45 +00002084
nethercote3d5e9102004-11-17 18:22:38 +00002085 PLAX_(__NR_clone, sys_clone), // 120
sewardja8d8e232005-06-07 20:04:56 +00002086//zz // (__NR_setdomainname, sys_setdomainname), // 121 */*(?)
nethercote3d5e9102004-11-17 18:22:38 +00002087 GENXY(__NR_uname, sys_newuname), // 122
2088 PLAX_(__NR_modify_ldt, sys_modify_ldt), // 123
sewardja8d8e232005-06-07 20:04:56 +00002089//zz LINXY(__NR_adjtimex, sys_adjtimex), // 124
2090//zz
nethercote3d5e9102004-11-17 18:22:38 +00002091 GENXY(__NR_mprotect, sys_mprotect), // 125
2092 GENXY(__NR_sigprocmask, sys_sigprocmask), // 126
sewardja8d8e232005-06-07 20:04:56 +00002093//zz // Nb: create_module() was removed 2.4-->2.6
nethercote3d5e9102004-11-17 18:22:38 +00002094 GENX_(__NR_create_module, sys_ni_syscall), // 127
sewardj696c5512005-06-08 23:38:32 +00002095 GENX_(__NR_init_module, sys_init_module), // 128
sewardja8d8e232005-06-07 20:04:56 +00002096//zz // (__NR_delete_module, sys_delete_module), // 129 (*/Linux)?
2097//zz
2098//zz // Nb: get_kernel_syms() was removed 2.4-->2.6
nethercote3d5e9102004-11-17 18:22:38 +00002099 GENX_(__NR_get_kernel_syms, sys_ni_syscall), // 130
sewardj696c5512005-06-08 23:38:32 +00002100 GENX_(__NR_quotactl, sys_quotactl), // 131
2101 GENX_(__NR_getpgid, sys_getpgid), // 132
2102 GENX_(__NR_fchdir, sys_fchdir), // 133
sewardja8d8e232005-06-07 20:04:56 +00002103//zz // (__NR_bdflush, sys_bdflush), // 134 */Linux
2104//zz
2105//zz // (__NR_sysfs, sys_sysfs), // 135 SVr4
sewardj696c5512005-06-08 23:38:32 +00002106 LINX_(__NR_personality, sys_personality), // 136
nethercote3d5e9102004-11-17 18:22:38 +00002107 GENX_(__NR_afs_syscall, sys_ni_syscall), // 137
sewardj696c5512005-06-08 23:38:32 +00002108 LINX_(__NR_setfsuid, sys_setfsuid16), // 138
2109 LINX_(__NR_setfsgid, sys_setfsgid16), // 139
2110
nethercote8ff888f2004-11-17 17:11:45 +00002111 LINXY(__NR__llseek, sys_llseek), // 140
sewardj78b50e42005-06-08 01:47:28 +00002112 GENXY(__NR_getdents, sys_getdents), // 141
nethercote3d5e9102004-11-17 18:22:38 +00002113 GENX_(__NR__newselect, sys_select), // 142
sewardj696c5512005-06-08 23:38:32 +00002114 GENX_(__NR_flock, sys_flock), // 143
2115 GENX_(__NR_msync, sys_msync), // 144
2116
nethercote3d5e9102004-11-17 18:22:38 +00002117 GENXY(__NR_readv, sys_readv), // 145
2118 GENX_(__NR_writev, sys_writev), // 146
sewardj696c5512005-06-08 23:38:32 +00002119 GENX_(__NR_getsid, sys_getsid), // 147
2120 GENX_(__NR_fdatasync, sys_fdatasync), // 148
nethercote8ff888f2004-11-17 17:11:45 +00002121 LINXY(__NR__sysctl, sys_sysctl), // 149
sewardj696c5512005-06-08 23:38:32 +00002122
2123 GENX_(__NR_mlock, sys_mlock), // 150
2124 GENX_(__NR_munlock, sys_munlock), // 151
2125 GENX_(__NR_mlockall, sys_mlockall), // 152
2126 GENX_(__NR_munlockall, sys_munlockall), // 153
sewardje6d5e722005-06-10 10:27:55 +00002127 GENXY(__NR_sched_setparam, sys_sched_setparam), // 154
2128
sewardj78b50e42005-06-08 01:47:28 +00002129 GENXY(__NR_sched_getparam, sys_sched_getparam), // 155
2130 GENX_(__NR_sched_setscheduler, sys_sched_setscheduler), // 156
2131 GENX_(__NR_sched_getscheduler, sys_sched_getscheduler), // 157
2132 GENX_(__NR_sched_yield, sys_sched_yield), // 158
2133 GENX_(__NR_sched_get_priority_max, sys_sched_get_priority_max),// 159
2134
2135 GENX_(__NR_sched_get_priority_min, sys_sched_get_priority_min),// 160
sewardja8d8e232005-06-07 20:04:56 +00002136//zz // (__NR_sched_rr_get_interval, sys_sched_rr_get_interval), // 161 */*
nethercote8ff888f2004-11-17 17:11:45 +00002137 GENXY(__NR_nanosleep, sys_nanosleep), // 162
2138 GENX_(__NR_mremap, sys_mremap), // 163
sewardje6d5e722005-06-10 10:27:55 +00002139 LINX_(__NR_setresuid, sys_setresuid16), // 164
2140
2141 LINXY(__NR_getresuid, sys_getresuid16), // 165
sewardja8d8e232005-06-07 20:04:56 +00002142//zz // (__NR_vm86, sys_vm86), // 166 x86/Linux-only
nethercote3d5e9102004-11-17 18:22:38 +00002143 GENX_(__NR_query_module, sys_ni_syscall), // 167
2144 GENXY(__NR_poll, sys_poll), // 168
sewardja8d8e232005-06-07 20:04:56 +00002145//zz // (__NR_nfsservctl, sys_nfsservctl), // 169 */Linux
2146//zz
sewardje6d5e722005-06-10 10:27:55 +00002147 LINX_(__NR_setresgid, sys_setresgid16), // 170
2148 LINXY(__NR_getresgid, sys_getresgid16), // 171
2149 LINX_(__NR_prctl, sys_prctl), // 172
sewardjd571aff2005-03-15 14:47:30 +00002150 PLAX_(__NR_rt_sigreturn, sys_rt_sigreturn), // 173 x86/Linux only?
nethercote3d5e9102004-11-17 18:22:38 +00002151 GENXY(__NR_rt_sigaction, sys_rt_sigaction), // 174
nethercote8ff888f2004-11-17 17:11:45 +00002152
nethercote3d5e9102004-11-17 18:22:38 +00002153 GENXY(__NR_rt_sigprocmask, sys_rt_sigprocmask), // 175
sewardje6d5e722005-06-10 10:27:55 +00002154 GENXY(__NR_rt_sigpending, sys_rt_sigpending), // 176
nethercote3d5e9102004-11-17 18:22:38 +00002155 GENXY(__NR_rt_sigtimedwait, sys_rt_sigtimedwait),// 177
sewardje6d5e722005-06-10 10:27:55 +00002156 GENXY(__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo),// 178
nethercote3d5e9102004-11-17 18:22:38 +00002157 GENX_(__NR_rt_sigsuspend, sys_rt_sigsuspend), // 179
sewardje6d5e722005-06-10 10:27:55 +00002158
2159 GENXY(__NR_pread64, sys_pread64), // 180
2160 GENX_(__NR_pwrite64, sys_pwrite64), // 181
2161 GENX_(__NR_chown, sys_chown16), // 182
nethercote3d5e9102004-11-17 18:22:38 +00002162 GENXY(__NR_getcwd, sys_getcwd), // 183
sewardje6d5e722005-06-10 10:27:55 +00002163 GENXY(__NR_capget, sys_capget), // 184
2164
2165 GENX_(__NR_capset, sys_capset), // 185
nethercote3d5e9102004-11-17 18:22:38 +00002166 GENXY(__NR_sigaltstack, sys_sigaltstack), // 186
sewardje6d5e722005-06-10 10:27:55 +00002167 LINXY(__NR_sendfile, sys_sendfile), // 187
2168 GENXY(__NR_getpmsg, sys_getpmsg), // 188
2169 GENX_(__NR_putpmsg, sys_putpmsg), // 189
nethercote8ff888f2004-11-17 17:11:45 +00002170
sewardjc93d7b62005-03-12 20:45:56 +00002171 // Nb: we treat vfork as fork
2172 GENX_(__NR_vfork, sys_fork), // 190
nethercote3d5e9102004-11-17 18:22:38 +00002173 GENXY(__NR_ugetrlimit, sys_getrlimit), // 191
2174 GENXY(__NR_mmap2, sys_mmap2), // 192
sewardje6d5e722005-06-10 10:27:55 +00002175 GENX_(__NR_truncate64, sys_truncate64), // 193
2176 GENX_(__NR_ftruncate64, sys_ftruncate64), // 194
2177
sewardja8d8e232005-06-07 20:04:56 +00002178 PLAXY(__NR_stat64, sys_stat64), // 195
2179 PLAXY(__NR_lstat64, sys_lstat64), // 196
2180 PLAXY(__NR_fstat64, sys_fstat64), // 197
sewardje6d5e722005-06-10 10:27:55 +00002181 GENX_(__NR_lchown32, sys_lchown), // 198
nethercote8ff888f2004-11-17 17:11:45 +00002182 GENX_(__NR_getuid32, sys_getuid), // 199
sewardj78b50e42005-06-08 01:47:28 +00002183
2184 GENX_(__NR_getgid32, sys_getgid), // 200
nethercote8ff888f2004-11-17 17:11:45 +00002185 GENX_(__NR_geteuid32, sys_geteuid), // 201
sewardj78b50e42005-06-08 01:47:28 +00002186 GENX_(__NR_getegid32, sys_getegid), // 202
sewardje6d5e722005-06-10 10:27:55 +00002187 GENX_(__NR_setreuid32, sys_setreuid), // 203
2188 GENX_(__NR_setregid32, sys_setregid), // 204
sewardj78b50e42005-06-08 01:47:28 +00002189
2190 GENXY(__NR_getgroups32, sys_getgroups), // 205
sewardje6d5e722005-06-10 10:27:55 +00002191 GENX_(__NR_setgroups32, sys_setgroups), // 206
2192 GENX_(__NR_fchown32, sys_fchown), // 207
2193 LINX_(__NR_setresuid32, sys_setresuid), // 208
sewardj78b50e42005-06-08 01:47:28 +00002194 LINXY(__NR_getresuid32, sys_getresuid), // 209
2195
sewardje6d5e722005-06-10 10:27:55 +00002196 LINX_(__NR_setresgid32, sys_setresgid), // 210
sewardj78b50e42005-06-08 01:47:28 +00002197 LINXY(__NR_getresgid32, sys_getresgid), // 211
sewardje6d5e722005-06-10 10:27:55 +00002198 GENX_(__NR_chown32, sys_chown), // 212
2199 GENX_(__NR_setuid32, sys_setuid), // 213
2200 GENX_(__NR_setgid32, sys_setgid), // 214
2201
2202 LINX_(__NR_setfsuid32, sys_setfsuid), // 215
2203 LINX_(__NR_setfsgid32, sys_setfsgid), // 216
sewardja8d8e232005-06-07 20:04:56 +00002204//zz // (__NR_pivot_root, sys_pivot_root), // 217 */Linux
sewardje6d5e722005-06-10 10:27:55 +00002205 GENXY(__NR_mincore, sys_mincore), // 218
nethercote3d5e9102004-11-17 18:22:38 +00002206 GENX_(__NR_madvise, sys_madvise), // 219
nethercote8ff888f2004-11-17 17:11:45 +00002207
nethercote3d5e9102004-11-17 18:22:38 +00002208 GENXY(__NR_getdents64, sys_getdents64), // 220
2209 GENXY(__NR_fcntl64, sys_fcntl64), // 221
2210 GENX_(222, sys_ni_syscall), // 222
2211 GENX_(223, sys_ni_syscall), // 223
sewardj8c257322005-06-08 01:01:48 +00002212 LINX_(__NR_gettid, sys_gettid), // 224
2213
sewardja8d8e232005-06-07 20:04:56 +00002214//zz // (__NR_readahead, sys_readahead), // 225 */(Linux?)
sewardje6d5e722005-06-10 10:27:55 +00002215 GENX_(__NR_setxattr, sys_setxattr), // 226
2216 GENX_(__NR_lsetxattr, sys_lsetxattr), // 227
2217 GENX_(__NR_fsetxattr, sys_fsetxattr), // 228
nethercote3d5e9102004-11-17 18:22:38 +00002218 GENXY(__NR_getxattr, sys_getxattr), // 229
sewardje6d5e722005-06-10 10:27:55 +00002219
2220 GENXY(__NR_lgetxattr, sys_lgetxattr), // 230
2221 GENXY(__NR_fgetxattr, sys_fgetxattr), // 231
2222 GENXY(__NR_listxattr, sys_listxattr), // 232
2223 GENXY(__NR_llistxattr, sys_llistxattr), // 233
2224 GENXY(__NR_flistxattr, sys_flistxattr), // 234
2225
2226 GENX_(__NR_removexattr, sys_removexattr), // 235
2227 GENX_(__NR_lremovexattr, sys_lremovexattr), // 236
2228 GENX_(__NR_fremovexattr, sys_fremovexattr), // 237
sewardja8d8e232005-06-07 20:04:56 +00002229//zz LINX_(__NR_tkill, sys_tkill), // 238 */Linux
sewardje6d5e722005-06-10 10:27:55 +00002230 LINXY(__NR_sendfile64, sys_sendfile64), // 239
2231
sewardjbc22cf72005-06-08 00:02:49 +00002232 LINXY(__NR_futex, sys_futex), // 240
sewardje6d5e722005-06-10 10:27:55 +00002233 GENX_(__NR_sched_setaffinity, sys_sched_setaffinity), // 241
2234 GENXY(__NR_sched_getaffinity, sys_sched_getaffinity), // 242
sewardjbc22cf72005-06-08 00:02:49 +00002235 PLAX_(__NR_set_thread_area, sys_set_thread_area), // 243
sewardje6d5e722005-06-10 10:27:55 +00002236 PLAX_(__NR_get_thread_area, sys_get_thread_area), // 244
2237
2238 LINX_(__NR_io_setup, sys_io_setup), // 245
2239 LINX_(__NR_io_destroy, sys_io_destroy), // 246
2240 LINXY(__NR_io_getevents, sys_io_getevents), // 247
2241 LINX_(__NR_io_submit, sys_io_submit), // 248
2242 LINXY(__NR_io_cancel, sys_io_cancel), // 249
2243
tom72440832005-06-15 10:31:10 +00002244 LINX_(__NR_fadvise64, sys_fadvise64), // 250 */(Linux?)
nethercote3d5e9102004-11-17 18:22:38 +00002245 GENX_(251, sys_ni_syscall), // 251
sewardjb5f6f512005-03-10 23:59:00 +00002246 LINX_(__NR_exit_group, sys_exit_group), // 252
sewardje6d5e722005-06-10 10:27:55 +00002247 GENXY(__NR_lookup_dcookie, sys_lookup_dcookie), // 253
2248 LINXY(__NR_epoll_create, sys_epoll_create), // 254
2249
2250 LINX_(__NR_epoll_ctl, sys_epoll_ctl), // 255
2251 LINXY(__NR_epoll_wait, sys_epoll_wait), // 256
sewardja8d8e232005-06-07 20:04:56 +00002252//zz // (__NR_remap_file_pages, sys_remap_file_pages), // 257 */Linux
sewardjbc22cf72005-06-08 00:02:49 +00002253 LINX_(__NR_set_tid_address, sys_set_tid_address), // 258
sewardje6d5e722005-06-10 10:27:55 +00002254 GENXY(__NR_timer_create, sys_timer_create), // 259
2255
2256 GENXY(__NR_timer_settime, sys_timer_settime), // (timer_create+1)
2257 GENXY(__NR_timer_gettime, sys_timer_gettime), // (timer_create+2)
2258 GENX_(__NR_timer_getoverrun, sys_timer_getoverrun),//(timer_create+3)
2259 GENX_(__NR_timer_delete, sys_timer_delete), // (timer_create+4)
2260 GENX_(__NR_clock_settime, sys_clock_settime), // (timer_create+5)
2261
nethercote3d5e9102004-11-17 18:22:38 +00002262 GENXY(__NR_clock_gettime, sys_clock_gettime), // (timer_create+6)
sewardje6d5e722005-06-10 10:27:55 +00002263 GENXY(__NR_clock_getres, sys_clock_getres), // (timer_create+7)
sewardja8d8e232005-06-07 20:04:56 +00002264//zz // (__NR_clock_nanosleep, sys_clock_nanosleep),// (timer_create+8) */*
sewardje6d5e722005-06-10 10:27:55 +00002265 GENXY(__NR_statfs64, sys_statfs64), // 268
2266 GENXY(__NR_fstatfs64, sys_fstatfs64), // 269
2267
sewardjbc22cf72005-06-08 00:02:49 +00002268 LINX_(__NR_tgkill, sys_tgkill), // 270 */Linux
sewardje6d5e722005-06-10 10:27:55 +00002269 GENX_(__NR_utimes, sys_utimes), // 271
tom72440832005-06-15 10:31:10 +00002270 LINX_(__NR_fadvise64_64, sys_fadvise64_64), // 272 */(Linux?)
nethercote3d5e9102004-11-17 18:22:38 +00002271 GENX_(__NR_vserver, sys_ni_syscall), // 273
sewardja8d8e232005-06-07 20:04:56 +00002272//zz // (__NR_mbind, sys_mbind), // 274 ?/?
2273//zz
2274//zz // (__NR_get_mempolicy, sys_get_mempolicy), // 275 ?/?
2275//zz // (__NR_set_mempolicy, sys_set_mempolicy), // 276 ?/?
sewardj8c257322005-06-08 01:01:48 +00002276 GENXY(__NR_mq_open, sys_mq_open), // 277
2277 GENX_(__NR_mq_unlink, sys_mq_unlink), // (mq_open+1)
sewardj8c9ea4e2005-06-08 10:46:56 +00002278 GENX_(__NR_mq_timedsend, sys_mq_timedsend), // (mq_open+2)
2279
2280 GENXY(__NR_mq_timedreceive, sys_mq_timedreceive),// (mq_open+3)
2281 GENX_(__NR_mq_notify, sys_mq_notify), // (mq_open+4)
2282 GENXY(__NR_mq_getsetattr, sys_mq_getsetattr), // (mq_open+5)
nethercote8ff888f2004-11-17 17:11:45 +00002283 GENX_(__NR_sys_kexec_load, sys_ni_syscall), // 283
2284};
2285
njnaf839f52005-06-23 03:27:57 +00002286const UInt ML_(syscall_table_size) =
2287 sizeof(ML_(syscall_table)) / sizeof(ML_(syscall_table)[0]);
nethercote8ff888f2004-11-17 17:11:45 +00002288
nethercote41c75da2004-10-18 15:34:14 +00002289/*--------------------------------------------------------------------*/
2290/*--- end ---*/
2291/*--------------------------------------------------------------------*/