blob: e277efe77912290e3c816a0c82b71a940e8f4fb0 [file] [log] [blame]
nethercote41c75da2004-10-18 15:34:14 +00001
2/*--------------------------------------------------------------------*/
njnc1b01812005-06-17 22:19:06 +00003/*--- Platform-specific syscalls stuff. syswrap-x86-linux.c ---*/
nethercote41c75da2004-10-18 15:34:14 +00004/*--------------------------------------------------------------------*/
5
6/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
nethercote41c75da2004-10-18 15:34:14 +00009
njn53612422005-03-12 16:22:54 +000010 Copyright (C) 2000-2005 Nicholas Nethercote
njn2bc10122005-05-08 02:10:27 +000011 njn@valgrind.org
nethercote41c75da2004-10-18 15:34:14 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
sewardjb5f6f512005-03-10 23:59:00 +000031/* TODO/FIXME jrs 20050207: assignments to the syscall return result
32 in interrupted_syscall() need to be reviewed. They don't seem
33 to assign the shadow state.
34*/
35
njnc7561b92005-06-19 01:24:32 +000036#include "pub_core_basics.h"
37#include "pub_core_threadstate.h"
sewardj45f4e7c2005-09-27 19:20:21 +000038#include "pub_core_debuginfo.h" // VG_(di_notify_mmap)
sewardj55f9d1a2005-04-25 11:11:44 +000039#include "pub_core_aspacemgr.h"
njn899ce732005-06-21 00:28:11 +000040#include "pub_core_debuglog.h"
sewardja8d8e232005-06-07 20:04:56 +000041#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000042#include "pub_core_libcassert.h"
njn36a20fa2005-06-03 03:08:39 +000043#include "pub_core_libcprint.h"
njnf39e9a32005-06-12 02:43:17 +000044#include "pub_core_libcproc.h"
njnde62cbf2005-06-10 22:08:14 +000045#include "pub_core_libcsignal.h"
njnaf1d7df2005-06-11 01:31:52 +000046#include "pub_core_mallocfree.h"
njnf4c50162005-06-20 14:18:12 +000047#include "pub_core_options.h"
njnc7561b92005-06-19 01:24:32 +000048#include "pub_core_scheduler.h"
njnf4c50162005-06-20 14:18:12 +000049#include "pub_core_sigframe.h" // For VG_(sigframe_destroy)()
njnde62cbf2005-06-10 22:08:14 +000050#include "pub_core_signals.h"
njn9abd6082005-06-17 21:31:45 +000051#include "pub_core_syscall.h"
njnc1b01812005-06-17 22:19:06 +000052#include "pub_core_syswrap.h"
njn43b9a8a2005-05-10 04:37:01 +000053#include "pub_core_tooliface.h"
sewardja8d8e232005-06-07 20:04:56 +000054
55#include "priv_types_n_macros.h"
njnc1b01812005-06-17 22:19:06 +000056#include "priv_syswrap-generic.h" /* for decls of generic wrappers */
57#include "priv_syswrap-linux.h" /* for decls of linux-ish wrappers */
sewardjce5a5662005-10-06 03:19:49 +000058#include "priv_syswrap-linux-variants.h" /* decls of linux variant wrappers */
njnc1b01812005-06-17 22:19:06 +000059#include "priv_syswrap-main.h"
sewardja8d8e232005-06-07 20:04:56 +000060
61#include "vki_unistd.h" /* for the __NR_* constants */
sewardj55f9d1a2005-04-25 11:11:44 +000062
sewardj4d89e302005-03-16 22:04:40 +000063
64/* ---------------------------------------------------------------------
njne1486662005-11-10 02:48:04 +000065 clone() handling
sewardj4d89e302005-03-16 22:04:40 +000066 ------------------------------------------------------------------ */
67
njnfcb7c3e2005-06-18 15:54:25 +000068/* Call f(arg1), but first switch stacks, using 'stack' as the new
69 stack, and use 'retaddr' as f's return-to address. Also, clear all
70 the integer registers before entering f.*/
71__attribute__((noreturn))
njna3afdfb2005-11-09 04:49:28 +000072void ML_(call_on_new_stack_0_1) ( Addr stack,
73 Addr retaddr,
74 void (*f)(Word),
75 Word arg1 );
njnfcb7c3e2005-06-18 15:54:25 +000076// 4(%esp) == stack
77// 8(%esp) == retaddr
78// 12(%esp) == f
79// 16(%esp) == arg1
80asm(
sewardjd9fc3822005-11-18 23:50:43 +000081".text\n"
njna3afdfb2005-11-09 04:49:28 +000082".globl vgModuleLocal_call_on_new_stack_0_1\n"
83"vgModuleLocal_call_on_new_stack_0_1:\n"
njnfcb7c3e2005-06-18 15:54:25 +000084" movl %esp, %esi\n" // remember old stack pointer
85" movl 4(%esi), %esp\n" // set stack
86" pushl 16(%esi)\n" // arg1 to stack
87" pushl 8(%esi)\n" // retaddr to stack
88" pushl 12(%esi)\n" // f to stack
89" movl $0, %eax\n" // zero all GP regs
90" movl $0, %ebx\n"
91" movl $0, %ecx\n"
92" movl $0, %edx\n"
93" movl $0, %esi\n"
94" movl $0, %edi\n"
95" movl $0, %ebp\n"
96" ret\n" // jump to f
97" ud2\n" // should never get here
sewardj2fedc642005-11-19 02:02:57 +000098".previous\n"
njnfcb7c3e2005-06-18 15:54:25 +000099);
100
101
sewardja8d8e232005-06-07 20:04:56 +0000102/*
103 Perform a clone system call. clone is strange because it has
104 fork()-like return-twice semantics, so it needs special
105 handling here.
106
107 Upon entry, we have:
108
109 int (fn)(void*) in 0+FSZ(%esp)
110 void* child_stack in 4+FSZ(%esp)
111 int flags in 8+FSZ(%esp)
112 void* arg in 12+FSZ(%esp)
113 pid_t* child_tid in 16+FSZ(%esp)
114 pid_t* parent_tid in 20+FSZ(%esp)
115 void* tls_ptr in 24+FSZ(%esp)
116
117 System call requires:
118
119 int $__NR_clone in %eax
120 int flags in %ebx
121 void* child_stack in %ecx
122 pid_t* parent_tid in %edx
123 pid_t* child_tid in %edi
124 void* tls_ptr in %esi
125
126 Returns an Int encoded in the linux-x86 way, not a SysRes.
127 */
tomf5d62be2005-07-18 12:02:45 +0000128#define FSZ "4+4+4+4" /* frame size = retaddr+ebx+edi+esi */
sewardj7d15e512005-09-30 01:20:47 +0000129#define __NR_CLONE VG_STRINGIFY(__NR_clone)
130#define __NR_EXIT VG_STRINGIFY(__NR_exit)
sewardja8d8e232005-06-07 20:04:56 +0000131
132extern
njnffd9c1d2005-11-10 04:02:19 +0000133Int do_syscall_clone_x86_linux ( Word (*fn)(void *),
sewardja8d8e232005-06-07 20:04:56 +0000134 void* stack,
135 Int flags,
136 void* arg,
137 Int* child_tid,
138 Int* parent_tid,
139 vki_modify_ldt_t * );
140asm(
sewardjd9fc3822005-11-18 23:50:43 +0000141".text\n"
sewardja8d8e232005-06-07 20:04:56 +0000142"do_syscall_clone_x86_linux:\n"
143" push %ebx\n"
144" push %edi\n"
tomf5d62be2005-07-18 12:02:45 +0000145" push %esi\n"
sewardja8d8e232005-06-07 20:04:56 +0000146
147 /* set up child stack with function and arg */
148" movl 4+"FSZ"(%esp), %ecx\n" /* syscall arg2: child stack */
149" movl 12+"FSZ"(%esp), %ebx\n" /* fn arg */
150" movl 0+"FSZ"(%esp), %eax\n" /* fn */
151" lea -8(%ecx), %ecx\n" /* make space on stack */
152" movl %ebx, 4(%ecx)\n" /* fn arg */
153" movl %eax, 0(%ecx)\n" /* fn */
154
155 /* get other args to clone */
156" movl 8+"FSZ"(%esp), %ebx\n" /* syscall arg1: flags */
157" movl 20+"FSZ"(%esp), %edx\n" /* syscall arg3: parent tid * */
tomb33fc682005-07-19 23:01:56 +0000158" movl 16+"FSZ"(%esp), %edi\n" /* syscall arg5: child tid * */
159" movl 24+"FSZ"(%esp), %esi\n" /* syscall arg4: tls_ptr * */
sewardja8d8e232005-06-07 20:04:56 +0000160" movl $"__NR_CLONE", %eax\n"
161" int $0x80\n" /* clone() */
162" testl %eax, %eax\n" /* child if retval == 0 */
163" jnz 1f\n"
164
165 /* CHILD - call thread function */
166" popl %eax\n"
167" call *%eax\n" /* call fn */
168
169 /* exit with result */
170" movl %eax, %ebx\n" /* arg1: return value from fn */
171" movl $"__NR_EXIT", %eax\n"
172" int $0x80\n"
173
174 /* Hm, exit returned */
175" ud2\n"
176
sewardje7aa4ae2005-06-09 12:43:42 +0000177"1:\n" /* PARENT or ERROR */
tomf5d62be2005-07-18 12:02:45 +0000178" pop %esi\n"
sewardja8d8e232005-06-07 20:04:56 +0000179" pop %edi\n"
180" pop %ebx\n"
181" ret\n"
sewardj2fedc642005-11-19 02:02:57 +0000182".previous\n"
sewardja8d8e232005-06-07 20:04:56 +0000183);
184
185#undef FSZ
186#undef __NR_CLONE
187#undef __NR_EXIT
sewardja8d8e232005-06-07 20:04:56 +0000188
sewardje7aa4ae2005-06-09 12:43:42 +0000189
njn2335d112005-05-15 20:52:04 +0000190// forward declarations
sewardj468dc792005-05-31 10:12:06 +0000191static void setup_child ( ThreadArchState*, ThreadArchState*, Bool );
sewardja8d8e232005-06-07 20:04:56 +0000192static SysRes sys_set_thread_area ( ThreadId, vki_modify_ldt_t* );
njn2335d112005-05-15 20:52:04 +0000193
194/*
sewardjb5f6f512005-03-10 23:59:00 +0000195 When a client clones, we need to keep track of the new thread. This means:
196 1. allocate a ThreadId+ThreadState+stack for the the thread
197
198 2. initialize the thread's new VCPU state
199
200 3. create the thread using the same args as the client requested,
201 but using the scheduler entrypoint for EIP, and a separate stack
202 for ESP.
203 */
sewardja8d8e232005-06-07 20:04:56 +0000204static SysRes do_clone ( ThreadId ptid,
205 UInt flags, Addr esp,
sewardje7aa4ae2005-06-09 12:43:42 +0000206 Int* parent_tidptr,
207 Int* child_tidptr,
sewardja8d8e232005-06-07 20:04:56 +0000208 vki_modify_ldt_t *tlsinfo)
sewardjb5f6f512005-03-10 23:59:00 +0000209{
210 static const Bool debug = False;
211
sewardja8d8e232005-06-07 20:04:56 +0000212 ThreadId ctid = VG_(alloc_ThreadState)();
213 ThreadState* ptst = VG_(get_ThreadState)(ptid);
214 ThreadState* ctst = VG_(get_ThreadState)(ctid);
215 UWord* stack;
sewardj45f4e7c2005-09-27 19:20:21 +0000216 NSegment* seg;
sewardja8d8e232005-06-07 20:04:56 +0000217 SysRes res;
218 Int eax;
sewardjb5f6f512005-03-10 23:59:00 +0000219 vki_sigset_t blockall, savedmask;
220
221 VG_(sigfillset)(&blockall);
222
223 vg_assert(VG_(is_running_thread)(ptid));
224 vg_assert(VG_(is_valid_tid)(ctid));
225
njna3afdfb2005-11-09 04:49:28 +0000226 stack = (UWord*)ML_(allocstack)(ctid);
sewardj45f4e7c2005-09-27 19:20:21 +0000227 if (stack == NULL) {
228 res = VG_(mk_SysRes_Error)( VKI_ENOMEM );
229 goto out;
230 }
sewardjb5f6f512005-03-10 23:59:00 +0000231
232 /* Copy register state
233
234 Both parent and child return to the same place, and the code
235 following the clone syscall works out which is which, so we
236 don't need to worry about it.
237
238 The parent gets the child's new tid returned from clone, but the
239 child gets 0.
240
241 If the clone call specifies a NULL esp for the new thread, then
242 it actually gets a copy of the parent's esp.
243 */
sewardj3d7c2f02005-07-24 07:15:44 +0000244 /* Note: the clone call done by the Quadrics Elan3 driver specifies
sewardj468dc792005-05-31 10:12:06 +0000245 clone flags of 0xF00, and it seems to rely on the assumption
sewardj3d7c2f02005-07-24 07:15:44 +0000246 that the child inherits a copy of the parent's GDT.
247 setup_child takes care of setting that up. */
248 setup_child( &ctst->arch, &ptst->arch, True );
sewardjb5f6f512005-03-10 23:59:00 +0000249
sewardje7aa4ae2005-06-09 12:43:42 +0000250 /* Make sys_clone appear to have returned Success(0) in the
251 child. */
sewardja8d8e232005-06-07 20:04:56 +0000252 ctst->arch.vex.guest_EAX = 0;
253
sewardjb5f6f512005-03-10 23:59:00 +0000254 if (esp != 0)
255 ctst->arch.vex.guest_ESP = esp;
256
257 ctst->os_state.parent = ptid;
sewardjb5f6f512005-03-10 23:59:00 +0000258
259 /* inherit signal mask */
njnaffd8782005-05-18 22:56:00 +0000260 ctst->sig_mask = ptst->sig_mask;
sewardjb5f6f512005-03-10 23:59:00 +0000261 ctst->tmp_sig_mask = ptst->sig_mask;
262
263 /* We don't really know where the client stack is, because its
264 allocated by the client. The best we can do is look at the
265 memory mappings and try to derive some useful information. We
266 assume that esp starts near its highest possible value, and can
267 only go down to the start of the mmaped segment. */
sewardj45f4e7c2005-09-27 19:20:21 +0000268 seg = VG_(am_find_nsegment)((Addr)esp);
269 if (seg && seg->kind != SkResvn) {
njn13bfd852005-06-02 03:52:53 +0000270 ctst->client_stack_highest_word = (Addr)VG_PGROUNDUP(esp);
sewardj45f4e7c2005-09-27 19:20:21 +0000271 ctst->client_stack_szB = ctst->client_stack_highest_word - seg->start;
sewardjb5f6f512005-03-10 23:59:00 +0000272
273 if (debug)
274 VG_(printf)("tid %d: guessed client stack range %p-%p\n",
sewardj45f4e7c2005-09-27 19:20:21 +0000275 ctid, seg->start, VG_PGROUNDUP(esp));
sewardjb5f6f512005-03-10 23:59:00 +0000276 } else {
277 VG_(message)(Vg_UserMsg, "!? New thread %d starts with ESP(%p) unmapped\n",
278 ctid, esp);
njn50ba34e2005-04-04 02:41:42 +0000279 ctst->client_stack_szB = 0;
sewardjb5f6f512005-03-10 23:59:00 +0000280 }
281
282 if (flags & VKI_CLONE_SETTLS) {
283 if (debug)
sewardja8d8e232005-06-07 20:04:56 +0000284 VG_(printf)("clone child has SETTLS: tls info at %p: idx=%d "
285 "base=%p limit=%x; esp=%p fs=%x gs=%x\n",
286 tlsinfo, tlsinfo->entry_number,
287 tlsinfo->base_addr, tlsinfo->limit,
sewardjb5f6f512005-03-10 23:59:00 +0000288 ptst->arch.vex.guest_ESP,
289 ctst->arch.vex.guest_FS, ctst->arch.vex.guest_GS);
sewardja8d8e232005-06-07 20:04:56 +0000290 res = sys_set_thread_area(ctid, tlsinfo);
291 if (res.isError)
sewardjb5f6f512005-03-10 23:59:00 +0000292 goto out;
293 }
294
295 flags &= ~VKI_CLONE_SETTLS;
296
297 /* start the thread with everything blocked */
298 VG_(sigprocmask)(VKI_SIG_SETMASK, &blockall, &savedmask);
299
300 /* Create the new thread */
sewardja8d8e232005-06-07 20:04:56 +0000301 eax = do_syscall_clone_x86_linux(
njna3afdfb2005-11-09 04:49:28 +0000302 ML_(start_thread_NORETURN), stack, flags, &VG_(threads)[ctid],
sewardja8d8e232005-06-07 20:04:56 +0000303 child_tidptr, parent_tidptr, NULL
304 );
cerion85665ca2005-06-20 15:51:07 +0000305 res = VG_(mk_SysRes_x86_linux)( eax );
sewardje7aa4ae2005-06-09 12:43:42 +0000306
sewardjb5f6f512005-03-10 23:59:00 +0000307 VG_(sigprocmask)(VKI_SIG_SETMASK, &savedmask, NULL);
308
309 out:
sewardja8d8e232005-06-07 20:04:56 +0000310 if (res.isError) {
sewardjb5f6f512005-03-10 23:59:00 +0000311 /* clone failed */
njnaf839f52005-06-23 03:27:57 +0000312 VG_(cleanup_thread)(&ctst->arch);
sewardjb5f6f512005-03-10 23:59:00 +0000313 ctst->status = VgTs_Empty;
314 }
315
sewardja8d8e232005-06-07 20:04:56 +0000316 return res;
sewardjb5f6f512005-03-10 23:59:00 +0000317}
318
sewardja8d8e232005-06-07 20:04:56 +0000319
nethercote8ff888f2004-11-17 17:11:45 +0000320/* ---------------------------------------------------------------------
njn2335d112005-05-15 20:52:04 +0000321 LDT/GDT simulation
322 ------------------------------------------------------------------ */
323
324/* Details of the LDT simulation
325 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
326
327 When a program runs natively, the linux kernel allows each *thread*
328 in it to have its own LDT. Almost all programs never do this --
329 it's wildly unportable, after all -- and so the kernel never
330 allocates the structure, which is just as well as an LDT occupies
331 64k of memory (8192 entries of size 8 bytes).
332
333 A thread may choose to modify its LDT entries, by doing the
334 __NR_modify_ldt syscall. In such a situation the kernel will then
335 allocate an LDT structure for it. Each LDT entry is basically a
336 (base, limit) pair. A virtual address in a specific segment is
337 translated to a linear address by adding the segment's base value.
338 In addition, the virtual address must not exceed the limit value.
339
340 To use an LDT entry, a thread loads one of the segment registers
341 (%cs, %ss, %ds, %es, %fs, %gs) with the index of the LDT entry (0
342 .. 8191) it wants to use. In fact, the required value is (index <<
343 3) + 7, but that's not important right now. Any normal instruction
344 which includes an addressing mode can then be made relative to that
345 LDT entry by prefixing the insn with a so-called segment-override
346 prefix, a byte which indicates which of the 6 segment registers
347 holds the LDT index.
348
349 Now, a key constraint is that valgrind's address checks operate in
350 terms of linear addresses. So we have to explicitly translate
351 virtual addrs into linear addrs, and that means doing a complete
352 LDT simulation.
353
354 Calls to modify_ldt are intercepted. For each thread, we maintain
355 an LDT (with the same normally-never-allocated optimisation that
356 the kernel does). This is updated as expected via calls to
357 modify_ldt.
358
359 When a thread does an amode calculation involving a segment
360 override prefix, the relevant LDT entry for the thread is
361 consulted. It all works.
362
363 There is a conceptual problem, which appears when switching back to
364 native execution, either temporarily to pass syscalls to the
365 kernel, or permanently, when debugging V. Problem at such points
366 is that it's pretty pointless to copy the simulated machine's
367 segment registers to the real machine, because we'd also need to
368 copy the simulated LDT into the real one, and that's prohibitively
369 expensive.
370
371 Fortunately it looks like no syscalls rely on the segment regs or
372 LDT being correct, so we can get away with it. Apart from that the
373 simulation is pretty straightforward. All 6 segment registers are
374 tracked, although only %ds, %es, %fs and %gs are allowed as
375 prefixes. Perhaps it could be restricted even more than that -- I
376 am not sure what is and isn't allowed in user-mode.
377*/
378
379/* Translate a struct modify_ldt_ldt_s to a VexGuestX86SegDescr, using
380 the Linux kernel's logic (cut-n-paste of code in
381 linux/kernel/ldt.c). */
382
383static
384void translate_to_hw_format ( /* IN */ vki_modify_ldt_t* inn,
sewardja8d8e232005-06-07 20:04:56 +0000385 /* OUT */ VexGuestX86SegDescr* out,
njn2335d112005-05-15 20:52:04 +0000386 Int oldmode )
387{
388 UInt entry_1, entry_2;
389 vg_assert(8 == sizeof(VexGuestX86SegDescr));
390
391 if (0)
392 VG_(printf)("translate_to_hw_format: base %p, limit %d\n",
393 inn->base_addr, inn->limit );
394
395 /* Allow LDTs to be cleared by the user. */
396 if (inn->base_addr == 0 && inn->limit == 0) {
397 if (oldmode ||
398 (inn->contents == 0 &&
399 inn->read_exec_only == 1 &&
400 inn->seg_32bit == 0 &&
401 inn->limit_in_pages == 0 &&
402 inn->seg_not_present == 1 &&
403 inn->useable == 0 )) {
404 entry_1 = 0;
405 entry_2 = 0;
406 goto install;
407 }
408 }
409
410 entry_1 = ((inn->base_addr & 0x0000ffff) << 16) |
411 (inn->limit & 0x0ffff);
412 entry_2 = (inn->base_addr & 0xff000000) |
413 ((inn->base_addr & 0x00ff0000) >> 16) |
414 (inn->limit & 0xf0000) |
415 ((inn->read_exec_only ^ 1) << 9) |
416 (inn->contents << 10) |
417 ((inn->seg_not_present ^ 1) << 15) |
418 (inn->seg_32bit << 22) |
419 (inn->limit_in_pages << 23) |
420 0x7000;
421 if (!oldmode)
422 entry_2 |= (inn->useable << 20);
423
424 /* Install the new entry ... */
425 install:
426 out->LdtEnt.Words.word1 = entry_1;
427 out->LdtEnt.Words.word2 = entry_2;
428}
429
430/* Create a zeroed-out GDT. */
431static VexGuestX86SegDescr* alloc_zeroed_x86_GDT ( void )
432{
433 Int nbytes = VEX_GUEST_X86_GDT_NENT * sizeof(VexGuestX86SegDescr);
434 return VG_(arena_calloc)(VG_AR_CORE, nbytes, 1);
435}
436
437/* Create a zeroed-out LDT. */
438static VexGuestX86SegDescr* alloc_zeroed_x86_LDT ( void )
439{
440 Int nbytes = VEX_GUEST_X86_LDT_NENT * sizeof(VexGuestX86SegDescr);
441 return VG_(arena_calloc)(VG_AR_CORE, nbytes, 1);
442}
443
444/* Free up an LDT or GDT allocated by the above fns. */
445static void free_LDT_or_GDT ( VexGuestX86SegDescr* dt )
446{
447 vg_assert(dt);
448 VG_(arena_free)(VG_AR_CORE, (void*)dt);
449}
450
451/* Copy contents between two existing LDTs. */
452static void copy_LDT_from_to ( VexGuestX86SegDescr* src,
453 VexGuestX86SegDescr* dst )
454{
sewardja8d8e232005-06-07 20:04:56 +0000455 Int i;
456 vg_assert(src);
457 vg_assert(dst);
458 for (i = 0; i < VEX_GUEST_X86_LDT_NENT; i++)
459 dst[i] = src[i];
njn2335d112005-05-15 20:52:04 +0000460}
461
sewardj468dc792005-05-31 10:12:06 +0000462/* Copy contents between two existing GDTs. */
463static void copy_GDT_from_to ( VexGuestX86SegDescr* src,
464 VexGuestX86SegDescr* dst )
465{
sewardja8d8e232005-06-07 20:04:56 +0000466 Int i;
467 vg_assert(src);
468 vg_assert(dst);
469 for (i = 0; i < VEX_GUEST_X86_GDT_NENT; i++)
470 dst[i] = src[i];
sewardj468dc792005-05-31 10:12:06 +0000471}
472
njn2335d112005-05-15 20:52:04 +0000473/* Free this thread's DTs, if it has any. */
474static void deallocate_LGDTs_for_thread ( VexGuestX86State* vex )
475{
476 vg_assert(sizeof(HWord) == sizeof(void*));
477
478 if (0)
479 VG_(printf)("deallocate_LGDTs_for_thread: "
480 "ldt = 0x%x, gdt = 0x%x\n",
481 vex->guest_LDT, vex->guest_GDT );
482
483 if (vex->guest_LDT != (HWord)NULL) {
484 free_LDT_or_GDT( (VexGuestX86SegDescr*)vex->guest_LDT );
485 vex->guest_LDT = (HWord)NULL;
486 }
487
488 if (vex->guest_GDT != (HWord)NULL) {
489 free_LDT_or_GDT( (VexGuestX86SegDescr*)vex->guest_GDT );
490 vex->guest_GDT = (HWord)NULL;
491 }
492}
493
494
495/*
496 * linux/kernel/ldt.c
497 *
498 * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds
499 * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
500 */
501
502/*
503 * read_ldt() is not really atomic - this is not a problem since
504 * synchronization of reads and writes done to the LDT has to be
505 * assured by user-space anyway. Writes are atomic, to protect
506 * the security checks done on new descriptors.
507 */
508static
sewardja8d8e232005-06-07 20:04:56 +0000509SysRes read_ldt ( ThreadId tid, UChar* ptr, UInt bytecount )
njn2335d112005-05-15 20:52:04 +0000510{
sewardja8d8e232005-06-07 20:04:56 +0000511 SysRes res;
njn2335d112005-05-15 20:52:04 +0000512 UInt i, size;
513 UChar* ldt;
514
515 if (0)
516 VG_(printf)("read_ldt: tid = %d, ptr = %p, bytecount = %d\n",
517 tid, ptr, bytecount );
518
519 vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*));
520 vg_assert(8 == sizeof(VexGuestX86SegDescr));
521
522 ldt = (Char*)(VG_(threads)[tid].arch.vex.guest_LDT);
sewardja8d8e232005-06-07 20:04:56 +0000523 res = VG_(mk_SysRes_Success)( 0 );
njn2335d112005-05-15 20:52:04 +0000524 if (ldt == NULL)
525 /* LDT not allocated, meaning all entries are null */
526 goto out;
527
528 size = VEX_GUEST_X86_LDT_NENT * sizeof(VexGuestX86SegDescr);
529 if (size > bytecount)
530 size = bytecount;
531
sewardja8d8e232005-06-07 20:04:56 +0000532 res = VG_(mk_SysRes_Success)( size );
njn2335d112005-05-15 20:52:04 +0000533 for (i = 0; i < size; i++)
534 ptr[i] = ldt[i];
535
536 out:
sewardja8d8e232005-06-07 20:04:56 +0000537 return res;
njn2335d112005-05-15 20:52:04 +0000538}
539
540
541static
sewardja8d8e232005-06-07 20:04:56 +0000542SysRes write_ldt ( ThreadId tid, void* ptr, UInt bytecount, Int oldmode )
njn2335d112005-05-15 20:52:04 +0000543{
sewardja8d8e232005-06-07 20:04:56 +0000544 SysRes res;
njn2335d112005-05-15 20:52:04 +0000545 VexGuestX86SegDescr* ldt;
546 vki_modify_ldt_t* ldt_info;
547
548 if (0)
549 VG_(printf)("write_ldt: tid = %d, ptr = %p, "
550 "bytecount = %d, oldmode = %d\n",
551 tid, ptr, bytecount, oldmode );
552
553 vg_assert(8 == sizeof(VexGuestX86SegDescr));
554 vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*));
555
556 ldt = (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_LDT;
557 ldt_info = (vki_modify_ldt_t*)ptr;
558
sewardja8d8e232005-06-07 20:04:56 +0000559 res = VG_(mk_SysRes_Error)( VKI_EINVAL );
njn2335d112005-05-15 20:52:04 +0000560 if (bytecount != sizeof(vki_modify_ldt_t))
561 goto out;
562
sewardja8d8e232005-06-07 20:04:56 +0000563 res = VG_(mk_SysRes_Error)( VKI_EINVAL );
njn2335d112005-05-15 20:52:04 +0000564 if (ldt_info->entry_number >= VEX_GUEST_X86_LDT_NENT)
565 goto out;
566 if (ldt_info->contents == 3) {
567 if (oldmode)
568 goto out;
569 if (ldt_info->seg_not_present == 0)
570 goto out;
571 }
572
573 /* If this thread doesn't have an LDT, we'd better allocate it
574 now. */
575 if (ldt == (HWord)NULL) {
576 ldt = alloc_zeroed_x86_LDT();
577 VG_(threads)[tid].arch.vex.guest_LDT = (HWord)ldt;
578 }
579
580 /* Install the new entry ... */
581 translate_to_hw_format ( ldt_info, &ldt[ldt_info->entry_number], oldmode );
sewardja8d8e232005-06-07 20:04:56 +0000582 res = VG_(mk_SysRes_Success)( 0 );
njn2335d112005-05-15 20:52:04 +0000583
584 out:
sewardja8d8e232005-06-07 20:04:56 +0000585 return res;
njn2335d112005-05-15 20:52:04 +0000586}
587
588
sewardja8d8e232005-06-07 20:04:56 +0000589static SysRes sys_modify_ldt ( ThreadId tid,
590 Int func, void* ptr, UInt bytecount )
njn2335d112005-05-15 20:52:04 +0000591{
sewardja8d8e232005-06-07 20:04:56 +0000592 SysRes ret = VG_(mk_SysRes_Error)( VKI_ENOSYS );
njn2335d112005-05-15 20:52:04 +0000593
594 switch (func) {
595 case 0:
596 ret = read_ldt(tid, ptr, bytecount);
597 break;
598 case 1:
599 ret = write_ldt(tid, ptr, bytecount, 1);
600 break;
601 case 2:
602 VG_(unimplemented)("sys_modify_ldt: func == 2");
603 /* god knows what this is about */
604 /* ret = read_default_ldt(ptr, bytecount); */
605 /*UNREACHED*/
606 break;
607 case 0x11:
608 ret = write_ldt(tid, ptr, bytecount, 0);
609 break;
610 }
611 return ret;
612}
613
614
sewardja8d8e232005-06-07 20:04:56 +0000615static SysRes sys_set_thread_area ( ThreadId tid, vki_modify_ldt_t* info )
njn2335d112005-05-15 20:52:04 +0000616{
sewardja8d8e232005-06-07 20:04:56 +0000617 Int idx;
njn2335d112005-05-15 20:52:04 +0000618 VexGuestX86SegDescr* gdt;
619
620 vg_assert(8 == sizeof(VexGuestX86SegDescr));
621 vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*));
622
623 if (info == NULL)
sewardja8d8e232005-06-07 20:04:56 +0000624 return VG_(mk_SysRes_Error)( VKI_EFAULT );
njn2335d112005-05-15 20:52:04 +0000625
626 gdt = (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_GDT;
627
628 /* If the thread doesn't have a GDT, allocate it now. */
629 if (!gdt) {
630 gdt = alloc_zeroed_x86_GDT();
631 VG_(threads)[tid].arch.vex.guest_GDT = (HWord)gdt;
632 }
633
634 idx = info->entry_number;
635
636 if (idx == -1) {
637 /* Find and use the first free entry. */
638 for (idx = 0; idx < VEX_GUEST_X86_GDT_NENT; idx++) {
639 if (gdt[idx].LdtEnt.Words.word1 == 0
640 && gdt[idx].LdtEnt.Words.word2 == 0)
641 break;
642 }
643
644 if (idx == VEX_GUEST_X86_GDT_NENT)
sewardja8d8e232005-06-07 20:04:56 +0000645 return VG_(mk_SysRes_Error)( VKI_ESRCH );
njn2335d112005-05-15 20:52:04 +0000646 } else if (idx < 0 || idx >= VEX_GUEST_X86_GDT_NENT) {
sewardja8d8e232005-06-07 20:04:56 +0000647 return VG_(mk_SysRes_Error)( VKI_EINVAL );
njn2335d112005-05-15 20:52:04 +0000648 }
649
650 translate_to_hw_format(info, &gdt[idx], 0);
651
652 VG_TRACK( pre_mem_write, Vg_CoreSysCall, tid,
653 "set_thread_area(info->entry)",
654 (Addr) & info->entry_number, sizeof(unsigned int) );
655 info->entry_number = idx;
656 VG_TRACK( post_mem_write, Vg_CoreSysCall, tid,
657 (Addr) & info->entry_number, sizeof(unsigned int) );
658
sewardja8d8e232005-06-07 20:04:56 +0000659 return VG_(mk_SysRes_Success)( 0 );
njn2335d112005-05-15 20:52:04 +0000660}
661
662
sewardje6d5e722005-06-10 10:27:55 +0000663static SysRes sys_get_thread_area ( ThreadId tid, vki_modify_ldt_t* info )
664{
665 Int idx;
666 VexGuestX86SegDescr* gdt;
667
668 vg_assert(sizeof(HWord) == sizeof(VexGuestX86SegDescr*));
669 vg_assert(8 == sizeof(VexGuestX86SegDescr));
670
671 if (info == NULL)
672 return VG_(mk_SysRes_Error)( VKI_EFAULT );
673
674 idx = info->entry_number;
675
676 if (idx < 0 || idx >= VEX_GUEST_X86_GDT_NENT)
677 return VG_(mk_SysRes_Error)( VKI_EINVAL );
678
679 gdt = (VexGuestX86SegDescr*)VG_(threads)[tid].arch.vex.guest_GDT;
680
681 /* If the thread doesn't have a GDT, allocate it now. */
682 if (!gdt) {
683 gdt = alloc_zeroed_x86_GDT();
684 VG_(threads)[tid].arch.vex.guest_GDT = (HWord)gdt;
685 }
686
687 info->base_addr = ( gdt[idx].LdtEnt.Bits.BaseHi << 24 ) |
688 ( gdt[idx].LdtEnt.Bits.BaseMid << 16 ) |
689 gdt[idx].LdtEnt.Bits.BaseLow;
690 info->limit = ( gdt[idx].LdtEnt.Bits.LimitHi << 16 ) |
691 gdt[idx].LdtEnt.Bits.LimitLow;
692 info->seg_32bit = gdt[idx].LdtEnt.Bits.Default_Big;
693 info->contents = ( gdt[idx].LdtEnt.Bits.Type >> 2 ) & 0x3;
694 info->read_exec_only = ( gdt[idx].LdtEnt.Bits.Type & 0x1 ) ^ 0x1;
695 info->limit_in_pages = gdt[idx].LdtEnt.Bits.Granularity;
696 info->seg_not_present = gdt[idx].LdtEnt.Bits.Pres ^ 0x1;
697 info->useable = gdt[idx].LdtEnt.Bits.Sys;
698 info->reserved = 0;
699
tom10c4b522005-07-19 22:44:33 +0000700 return VG_(mk_SysRes_Success)( 0 );
sewardje6d5e722005-06-10 10:27:55 +0000701}
njn2335d112005-05-15 20:52:04 +0000702
703/* ---------------------------------------------------------------------
704 More thread stuff
705 ------------------------------------------------------------------ */
706
njnaf839f52005-06-23 03:27:57 +0000707void VG_(cleanup_thread) ( ThreadArchState* arch )
njn2335d112005-05-15 20:52:04 +0000708{
709 /* Release arch-specific resources held by this thread. */
710 /* On x86, we have to dump the LDT and GDT. */
711 deallocate_LGDTs_for_thread( &arch->vex );
712}
713
714
715static void setup_child ( /*OUT*/ ThreadArchState *child,
sewardj468dc792005-05-31 10:12:06 +0000716 /*IN*/ ThreadArchState *parent,
717 Bool inherit_parents_GDT )
njn2335d112005-05-15 20:52:04 +0000718{
719 /* We inherit our parent's guest state. */
720 child->vex = parent->vex;
721 child->vex_shadow = parent->vex_shadow;
sewardj468dc792005-05-31 10:12:06 +0000722
njn2335d112005-05-15 20:52:04 +0000723 /* We inherit our parent's LDT. */
724 if (parent->vex.guest_LDT == (HWord)NULL) {
725 /* We hope this is the common case. */
726 child->vex.guest_LDT = (HWord)NULL;
727 } else {
728 /* No luck .. we have to take a copy of the parent's. */
729 child->vex.guest_LDT = (HWord)alloc_zeroed_x86_LDT();
730 copy_LDT_from_to( (VexGuestX86SegDescr*)parent->vex.guest_LDT,
731 (VexGuestX86SegDescr*)child->vex.guest_LDT );
732 }
733
sewardj468dc792005-05-31 10:12:06 +0000734 /* Either we start with an empty GDT (the usual case) or inherit a
735 copy of our parents' one (Quadrics Elan3 driver -style clone
736 only). */
njn2335d112005-05-15 20:52:04 +0000737 child->vex.guest_GDT = (HWord)NULL;
sewardj468dc792005-05-31 10:12:06 +0000738
739 if (inherit_parents_GDT && parent->vex.guest_GDT != (HWord)NULL) {
740 child->vex.guest_GDT = (HWord)alloc_zeroed_x86_GDT();
741 copy_GDT_from_to( (VexGuestX86SegDescr*)parent->vex.guest_GDT,
742 (VexGuestX86SegDescr*)child->vex.guest_GDT );
743 }
njn2335d112005-05-15 20:52:04 +0000744}
745
sewardja8d8e232005-06-07 20:04:56 +0000746
njn2335d112005-05-15 20:52:04 +0000747/* ---------------------------------------------------------------------
nethercote8ff888f2004-11-17 17:11:45 +0000748 PRE/POST wrappers for x86/Linux-specific syscalls
749 ------------------------------------------------------------------ */
750
sewardja8d8e232005-06-07 20:04:56 +0000751#define PRE(name) DEFN_PRE_TEMPLATE(x86_linux, name)
752#define POST(name) DEFN_POST_TEMPLATE(x86_linux, name)
nethercote8ff888f2004-11-17 17:11:45 +0000753
sewardja8d8e232005-06-07 20:04:56 +0000754/* Add prototypes for the wrappers declared here, so that gcc doesn't
755 harass us for not having prototypes. Really this is a kludge --
756 the right thing to do is to make these wrappers 'static' since they
757 aren't visible outside this file, but that requires even more macro
758 magic. */
759DECL_TEMPLATE(x86_linux, sys_socketcall);
760DECL_TEMPLATE(x86_linux, sys_stat64);
761DECL_TEMPLATE(x86_linux, sys_fstat64);
762DECL_TEMPLATE(x86_linux, sys_lstat64);
763DECL_TEMPLATE(x86_linux, sys_clone);
764DECL_TEMPLATE(x86_linux, old_mmap);
tom9548a162005-09-30 08:07:53 +0000765DECL_TEMPLATE(x86_linux, sys_mmap2);
sewardja8d8e232005-06-07 20:04:56 +0000766DECL_TEMPLATE(x86_linux, sys_sigreturn);
767DECL_TEMPLATE(x86_linux, sys_ipc);
768DECL_TEMPLATE(x86_linux, sys_rt_sigreturn);
769DECL_TEMPLATE(x86_linux, sys_modify_ldt);
sewardjbc22cf72005-06-08 00:02:49 +0000770DECL_TEMPLATE(x86_linux, sys_set_thread_area);
sewardje6d5e722005-06-10 10:27:55 +0000771DECL_TEMPLATE(x86_linux, sys_get_thread_area);
sewardj8c257322005-06-08 01:01:48 +0000772DECL_TEMPLATE(x86_linux, sys_ptrace);
sewardj696c5512005-06-08 23:38:32 +0000773DECL_TEMPLATE(x86_linux, sys_sigaction);
774DECL_TEMPLATE(x86_linux, old_select);
tomc1369aa2006-02-11 16:26:46 +0000775DECL_TEMPLATE(x86_linux, sys_vm86old);
776DECL_TEMPLATE(x86_linux, sys_vm86);
sewardjce5a5662005-10-06 03:19:49 +0000777DECL_TEMPLATE(x86_linux, sys_syscall223);
nethercote8ff888f2004-11-17 17:11:45 +0000778
sewardj696c5512005-06-08 23:38:32 +0000779PRE(old_select)
780{
781 /* struct sel_arg_struct {
782 unsigned long n;
783 fd_set *inp, *outp, *exp;
784 struct timeval *tvp;
785 };
786 */
787 PRE_REG_READ1(long, "old_select", struct sel_arg_struct *, args);
788 PRE_MEM_READ( "old_select(args)", ARG1, 5*sizeof(UWord) );
789 *flags |= SfMayBlock;
790 {
791 UInt* arg_struct = (UInt*)ARG1;
792 UInt a1, a2, a3, a4, a5;
793
794 a1 = arg_struct[0];
795 a2 = arg_struct[1];
796 a3 = arg_struct[2];
797 a4 = arg_struct[3];
798 a5 = arg_struct[4];
799
800 PRINT("old_select ( %d, %p, %p, %p, %p )", a1,a2,a3,a4,a5);
801 if (a2 != (Addr)NULL)
802 PRE_MEM_READ( "old_select(readfds)", a2, a1/8 /* __FD_SETSIZE/8 */ );
803 if (a3 != (Addr)NULL)
804 PRE_MEM_READ( "old_select(writefds)", a3, a1/8 /* __FD_SETSIZE/8 */ );
805 if (a4 != (Addr)NULL)
806 PRE_MEM_READ( "old_select(exceptfds)", a4, a1/8 /* __FD_SETSIZE/8 */ );
807 if (a5 != (Addr)NULL)
808 PRE_MEM_READ( "old_select(timeout)", a5, sizeof(struct vki_timeval) );
809 }
810}
nethercote3d5e9102004-11-17 18:22:38 +0000811
sewardja8d8e232005-06-07 20:04:56 +0000812PRE(sys_clone)
nethercote3d5e9102004-11-17 18:22:38 +0000813{
sewardjb5f6f512005-03-10 23:59:00 +0000814 UInt cloneflags;
nethercote3d5e9102004-11-17 18:22:38 +0000815
sewardjb5f6f512005-03-10 23:59:00 +0000816 PRINT("sys_clone ( %x, %p, %p, %p, %p )",ARG1,ARG2,ARG3,ARG4,ARG5);
817 PRE_REG_READ5(int, "clone",
818 unsigned long, flags,
819 void *, child_stack,
820 int *, parent_tidptr,
821 vki_modify_ldt_t *, tlsinfo,
822 int *, child_tidptr);
823
824 if (ARG1 & VKI_CLONE_PARENT_SETTID) {
825 PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
sewardj45f4e7c2005-09-27 19:20:21 +0000826 if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int),
827 VKI_PROT_WRITE)) {
sewardja8d8e232005-06-07 20:04:56 +0000828 SET_STATUS_Failure( VKI_EFAULT );
sewardjb5f6f512005-03-10 23:59:00 +0000829 return;
830 }
nethercote3d5e9102004-11-17 18:22:38 +0000831 }
sewardjb5f6f512005-03-10 23:59:00 +0000832 if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
833 PRE_MEM_WRITE("clone(child_tidptr)", ARG5, sizeof(Int));
sewardj45f4e7c2005-09-27 19:20:21 +0000834 if (!VG_(am_is_valid_for_client)(ARG5, sizeof(Int),
835 VKI_PROT_WRITE)) {
sewardja8d8e232005-06-07 20:04:56 +0000836 SET_STATUS_Failure( VKI_EFAULT );
sewardjb5f6f512005-03-10 23:59:00 +0000837 return;
838 }
839 }
840 if (ARG1 & VKI_CLONE_SETTLS) {
841 PRE_MEM_READ("clone(tls_user_desc)", ARG4, sizeof(vki_modify_ldt_t));
sewardj45f4e7c2005-09-27 19:20:21 +0000842 if (!VG_(am_is_valid_for_client)(ARG4, sizeof(vki_modify_ldt_t),
843 VKI_PROT_READ)) {
sewardja8d8e232005-06-07 20:04:56 +0000844 SET_STATUS_Failure( VKI_EFAULT );
sewardjb5f6f512005-03-10 23:59:00 +0000845 return;
846 }
847 }
848
849 cloneflags = ARG1;
850
sewardj7eb7c582005-06-23 01:02:53 +0000851 if (!ML_(client_signal_OK)(ARG1 & VKI_CSIGNAL)) {
sewardja8d8e232005-06-07 20:04:56 +0000852 SET_STATUS_Failure( VKI_EINVAL );
sewardjb5f6f512005-03-10 23:59:00 +0000853 return;
854 }
855
sewardj468dc792005-05-31 10:12:06 +0000856 /* Be ultra-paranoid and filter out any clone-variants we don't understand:
857 - ??? specifies clone flags of 0x100011
858 - ??? specifies clone flags of 0x1200011.
859 - NPTL specifies clone flags of 0x7D0F00.
860 - The Quadrics Elan3 driver specifies clone flags of 0xF00.
sewardjde2b1602005-11-05 15:13:23 +0000861 - Newer Quadrics Elan3 drivers with NTPL support specify 0x410F00.
sewardj468dc792005-05-31 10:12:06 +0000862 Everything else is rejected.
863 */
sewardj934d2d52005-05-31 13:08:03 +0000864 if (
sewardjde2b1602005-11-05 15:13:23 +0000865 1 ||
866 /* 11 Nov 05: for the time being, disable this ultra-paranoia.
867 The switch below probably does a good enough job. */
sewardj934d2d52005-05-31 13:08:03 +0000868 (cloneflags == 0x100011 || cloneflags == 0x1200011
869 || cloneflags == 0x7D0F00
sewardja8d8e232005-06-07 20:04:56 +0000870 || cloneflags == 0x790F00
sewardjd15ce0c2005-05-31 21:07:01 +0000871 || cloneflags == 0x3D0F00
sewardjde2b1602005-11-05 15:13:23 +0000872 || cloneflags == 0x410F00
sewardj934d2d52005-05-31 13:08:03 +0000873 || cloneflags == 0xF00
874 || cloneflags == 0xF21)) {
875 /* OK */
sewardj468dc792005-05-31 10:12:06 +0000876 }
877 else {
878 /* Nah. We don't like it. Go away. */
879 goto reject;
880 }
881
sewardjb5f6f512005-03-10 23:59:00 +0000882 /* Only look at the flags we really care about */
sewardja8d8e232005-06-07 20:04:56 +0000883 switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS
884 | VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
sewardjb5f6f512005-03-10 23:59:00 +0000885 case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
886 /* thread creation */
sewardja8d8e232005-06-07 20:04:56 +0000887 SET_STATUS_from_SysRes(
888 do_clone(tid,
889 ARG1, /* flags */
890 (Addr)ARG2, /* child ESP */
891 (Int *)ARG3, /* parent_tidptr */
892 (Int *)ARG5, /* child_tidptr */
893 (vki_modify_ldt_t *)ARG4)); /* set_tls */
sewardjb5f6f512005-03-10 23:59:00 +0000894 break;
895
896 case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
897 /* FALLTHROUGH - assume vfork == fork */
898 cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
899
900 case 0: /* plain fork */
sewardja8d8e232005-06-07 20:04:56 +0000901 SET_STATUS_from_SysRes(
njne1486662005-11-10 02:48:04 +0000902 ML_(do_fork_clone)(tid,
sewardje7aa4ae2005-06-09 12:43:42 +0000903 cloneflags, /* flags */
sewardja8d8e232005-06-07 20:04:56 +0000904 (Int *)ARG3, /* parent_tidptr */
905 (Int *)ARG5)); /* child_tidptr */
sewardjb5f6f512005-03-10 23:59:00 +0000906 break;
907
908 default:
sewardj468dc792005-05-31 10:12:06 +0000909 reject:
sewardjb5f6f512005-03-10 23:59:00 +0000910 /* should we just ENOSYS? */
sewardj468dc792005-05-31 10:12:06 +0000911 VG_(message)(Vg_UserMsg, "");
912 VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%x", ARG1);
913 VG_(message)(Vg_UserMsg, "");
sewardj468dc792005-05-31 10:12:06 +0000914 VG_(message)(Vg_UserMsg, "The only supported clone() uses are:");
915 VG_(message)(Vg_UserMsg, " - via a threads library (LinuxThreads or NPTL)");
916 VG_(message)(Vg_UserMsg, " - via the implementation of fork or vfork");
917 VG_(message)(Vg_UserMsg, " - for the Quadrics Elan3 user-space driver");
sewardjb5f6f512005-03-10 23:59:00 +0000918 VG_(unimplemented)
sewardj468dc792005-05-31 10:12:06 +0000919 ("Valgrind does not support general clone().");
sewardjb5f6f512005-03-10 23:59:00 +0000920 }
921
sewardja8d8e232005-06-07 20:04:56 +0000922 if (SUCCESS) {
sewardjb5f6f512005-03-10 23:59:00 +0000923 if (ARG1 & VKI_CLONE_PARENT_SETTID)
924 POST_MEM_WRITE(ARG3, sizeof(Int));
925 if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID))
926 POST_MEM_WRITE(ARG5, sizeof(Int));
927
928 /* Thread creation was successful; let the child have the chance
929 to run */
sewardja8d8e232005-06-07 20:04:56 +0000930 *flags |= SfYieldAfter;
sewardjb5f6f512005-03-10 23:59:00 +0000931 }
932}
933
sewardja8d8e232005-06-07 20:04:56 +0000934PRE(sys_sigreturn)
sewardjb5f6f512005-03-10 23:59:00 +0000935{
sewardja8d8e232005-06-07 20:04:56 +0000936 ThreadState* tst;
sewardjb5f6f512005-03-10 23:59:00 +0000937 PRINT("sigreturn ( )");
938
sewardja8d8e232005-06-07 20:04:56 +0000939 vg_assert(VG_(is_valid_tid)(tid));
940 vg_assert(tid >= 1 && tid < VG_N_THREADS);
941 vg_assert(VG_(is_running_thread)(tid));
942
sewardjb5f6f512005-03-10 23:59:00 +0000943 /* Adjust esp to point to start of frame; skip back up over
944 sigreturn sequence's "popl %eax" and handler ret addr */
sewardja8d8e232005-06-07 20:04:56 +0000945 tst = VG_(get_ThreadState)(tid);
sewardjb5f6f512005-03-10 23:59:00 +0000946 tst->arch.vex.guest_ESP -= sizeof(Addr)+sizeof(Word);
947
948 /* This is only so that the EIP is (might be) useful to report if
949 something goes wrong in the sigreturn */
sewardj7eb7c582005-06-23 01:02:53 +0000950 ML_(fixup_guest_state_to_restart_syscall)(&tst->arch);
sewardjb5f6f512005-03-10 23:59:00 +0000951
sewardj985fabb2005-04-24 14:18:14 +0000952 VG_(sigframe_destroy)(tid, False);
sewardjb5f6f512005-03-10 23:59:00 +0000953
sewardja8d8e232005-06-07 20:04:56 +0000954 /* For unclear reasons, it appears we need the syscall to return
955 without changing %EAX. Since %EAX is the return value, and can
956 denote either success or failure, we must set up so that the
957 driver logic copies it back unchanged. Also, note %EAX is of
958 the guest registers written by VG_(sigframe_destroy). */
cerion85665ca2005-06-20 15:51:07 +0000959 SET_STATUS_from_SysRes( VG_(mk_SysRes_x86_linux)( tst->arch.vex.guest_EAX ) );
sewardjb5f6f512005-03-10 23:59:00 +0000960
sewardja8d8e232005-06-07 20:04:56 +0000961 /* Check to see if some any signals arose as a result of this. */
962 *flags |= SfPollAfter;
nethercote3d5e9102004-11-17 18:22:38 +0000963}
964
sewardja8d8e232005-06-07 20:04:56 +0000965PRE(sys_rt_sigreturn)
sewardjd571aff2005-03-15 14:47:30 +0000966{
sewardja8d8e232005-06-07 20:04:56 +0000967 ThreadState* tst;
sewardjd571aff2005-03-15 14:47:30 +0000968 PRINT("rt_sigreturn ( )");
969
sewardja8d8e232005-06-07 20:04:56 +0000970 vg_assert(VG_(is_valid_tid)(tid));
971 vg_assert(tid >= 1 && tid < VG_N_THREADS);
972 vg_assert(VG_(is_running_thread)(tid));
973
sewardjd571aff2005-03-15 14:47:30 +0000974 /* Adjust esp to point to start of frame; skip back up over handler
975 ret addr */
sewardja8d8e232005-06-07 20:04:56 +0000976 tst = VG_(get_ThreadState)(tid);
sewardjd571aff2005-03-15 14:47:30 +0000977 tst->arch.vex.guest_ESP -= sizeof(Addr);
978
979 /* This is only so that the EIP is (might be) useful to report if
980 something goes wrong in the sigreturn */
sewardj7eb7c582005-06-23 01:02:53 +0000981 ML_(fixup_guest_state_to_restart_syscall)(&tst->arch);
sewardjd571aff2005-03-15 14:47:30 +0000982
sewardj5bcde922005-05-03 22:31:22 +0000983 VG_(sigframe_destroy)(tid, True);
sewardjd571aff2005-03-15 14:47:30 +0000984
sewardja8d8e232005-06-07 20:04:56 +0000985 /* For unclear reasons, it appears we need the syscall to return
986 without changing %EAX. Since %EAX is the return value, and can
987 denote either success or failure, we must set up so that the
988 driver logic copies it back unchanged. Also, note %EAX is of
989 the guest registers written by VG_(sigframe_destroy). */
cerion85665ca2005-06-20 15:51:07 +0000990 SET_STATUS_from_SysRes( VG_(mk_SysRes_x86_linux)( tst->arch.vex.guest_EAX ) );
sewardjd571aff2005-03-15 14:47:30 +0000991
sewardja8d8e232005-06-07 20:04:56 +0000992 /* Check to see if some any signals arose as a result of this. */
993 *flags |= SfPollAfter;
sewardjd571aff2005-03-15 14:47:30 +0000994}
995
sewardja8d8e232005-06-07 20:04:56 +0000996PRE(sys_modify_ldt)
nethercote8ff888f2004-11-17 17:11:45 +0000997{
njn22cfccb2004-11-27 16:10:23 +0000998 PRINT("sys_modify_ldt ( %d, %p, %d )", ARG1,ARG2,ARG3);
nethercote8ff888f2004-11-17 17:11:45 +0000999 PRE_REG_READ3(int, "modify_ldt", int, func, void *, ptr,
1000 unsigned long, bytecount);
1001
njn22cfccb2004-11-27 16:10:23 +00001002 if (ARG1 == 0) {
nethercote8ff888f2004-11-17 17:11:45 +00001003 /* read the LDT into ptr */
njn22cfccb2004-11-27 16:10:23 +00001004 PRE_MEM_WRITE( "modify_ldt(ptr)", ARG2, ARG3 );
nethercote8ff888f2004-11-17 17:11:45 +00001005 }
njn22cfccb2004-11-27 16:10:23 +00001006 if (ARG1 == 1 || ARG1 == 0x11) {
nethercote8ff888f2004-11-17 17:11:45 +00001007 /* write the LDT with the entry pointed at by ptr */
njn22cfccb2004-11-27 16:10:23 +00001008 PRE_MEM_READ( "modify_ldt(ptr)", ARG2, sizeof(vki_modify_ldt_t) );
nethercote8ff888f2004-11-17 17:11:45 +00001009 }
1010 /* "do" the syscall ourselves; the kernel never sees it */
sewardja8d8e232005-06-07 20:04:56 +00001011 SET_STATUS_from_SysRes( sys_modify_ldt( tid, ARG1, (void*)ARG2, ARG3 ) );
nethercote8ff888f2004-11-17 17:11:45 +00001012
sewardja8d8e232005-06-07 20:04:56 +00001013 if (ARG1 == 0 && SUCCESS && RES > 0) {
njn22cfccb2004-11-27 16:10:23 +00001014 POST_MEM_WRITE( ARG2, RES );
nethercote8ff888f2004-11-17 17:11:45 +00001015 }
1016}
1017
sewardjbc22cf72005-06-08 00:02:49 +00001018PRE(sys_set_thread_area)
1019{
1020 PRINT("sys_set_thread_area ( %p )", ARG1);
1021 PRE_REG_READ1(int, "set_thread_area", struct user_desc *, u_info)
1022 PRE_MEM_READ( "set_thread_area(u_info)", ARG1, sizeof(vki_modify_ldt_t) );
1023
1024 /* "do" the syscall ourselves; the kernel never sees it */
1025 SET_STATUS_from_SysRes( sys_set_thread_area( tid, (void *)ARG1 ) );
1026}
1027
sewardje6d5e722005-06-10 10:27:55 +00001028PRE(sys_get_thread_area)
1029{
1030 PRINT("sys_get_thread_area ( %p )", ARG1);
1031 PRE_REG_READ1(int, "get_thread_area", struct user_desc *, u_info)
1032 PRE_MEM_WRITE( "get_thread_area(u_info)", ARG1, sizeof(vki_modify_ldt_t) );
1033
1034 /* "do" the syscall ourselves; the kernel never sees it */
1035 SET_STATUS_from_SysRes( sys_get_thread_area( tid, (void *)ARG1 ) );
1036
1037 if (SUCCESS) {
1038 POST_MEM_WRITE( ARG1, sizeof(vki_modify_ldt_t) );
1039 }
1040}
sewardj8c257322005-06-08 01:01:48 +00001041
1042// Parts of this are x86-specific, but the *PEEK* cases are generic.
1043// XXX: Why is the memory pointed to by ARG3 never checked?
1044PRE(sys_ptrace)
1045{
1046 PRINT("sys_ptrace ( %d, %d, %p, %p )", ARG1,ARG2,ARG3,ARG4);
1047 PRE_REG_READ4(int, "ptrace",
1048 long, request, long, pid, long, addr, long, data);
1049 switch (ARG1) {
1050 case VKI_PTRACE_PEEKTEXT:
1051 case VKI_PTRACE_PEEKDATA:
1052 case VKI_PTRACE_PEEKUSR:
1053 PRE_MEM_WRITE( "ptrace(peek)", ARG4,
1054 sizeof (long));
1055 break;
1056 case VKI_PTRACE_GETREGS:
1057 PRE_MEM_WRITE( "ptrace(getregs)", ARG4,
1058 sizeof (struct vki_user_regs_struct));
1059 break;
1060 case VKI_PTRACE_GETFPREGS:
1061 PRE_MEM_WRITE( "ptrace(getfpregs)", ARG4,
1062 sizeof (struct vki_user_i387_struct));
1063 break;
1064 case VKI_PTRACE_GETFPXREGS:
1065 PRE_MEM_WRITE( "ptrace(getfpxregs)", ARG4,
1066 sizeof(struct vki_user_fxsr_struct) );
1067 break;
1068 case VKI_PTRACE_SETREGS:
1069 PRE_MEM_READ( "ptrace(setregs)", ARG4,
1070 sizeof (struct vki_user_regs_struct));
1071 break;
1072 case VKI_PTRACE_SETFPREGS:
1073 PRE_MEM_READ( "ptrace(setfpregs)", ARG4,
1074 sizeof (struct vki_user_i387_struct));
1075 break;
1076 case VKI_PTRACE_SETFPXREGS:
1077 PRE_MEM_READ( "ptrace(setfpxregs)", ARG4,
1078 sizeof(struct vki_user_fxsr_struct) );
1079 break;
1080 default:
1081 break;
1082 }
1083}
1084
1085POST(sys_ptrace)
1086{
1087 switch (ARG1) {
1088 case VKI_PTRACE_PEEKTEXT:
1089 case VKI_PTRACE_PEEKDATA:
1090 case VKI_PTRACE_PEEKUSR:
1091 POST_MEM_WRITE( ARG4, sizeof (long));
1092 break;
1093 case VKI_PTRACE_GETREGS:
1094 POST_MEM_WRITE( ARG4, sizeof (struct vki_user_regs_struct));
1095 break;
1096 case VKI_PTRACE_GETFPREGS:
1097 POST_MEM_WRITE( ARG4, sizeof (struct vki_user_i387_struct));
1098 break;
1099 case VKI_PTRACE_GETFPXREGS:
1100 POST_MEM_WRITE( ARG4, sizeof(struct vki_user_fxsr_struct) );
1101 break;
1102 default:
1103 break;
1104 }
1105}
njnca0518d2004-11-26 19:34:36 +00001106
njnb249fd72004-11-29 14:24:57 +00001107static Addr deref_Addr ( ThreadId tid, Addr a, Char* s )
1108{
1109 Addr* a_p = (Addr*)a;
1110 PRE_MEM_READ( s, (Addr)a_p, sizeof(Addr) );
1111 return *a_p;
1112}
njnc6168192004-11-29 13:54:10 +00001113
sewardja8d8e232005-06-07 20:04:56 +00001114PRE(sys_ipc)
njnc6168192004-11-29 13:54:10 +00001115{
1116 PRINT("sys_ipc ( %d, %d, %d, %d, %p, %d )", ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
1117 // XXX: this is simplistic -- some args are not used in all circumstances.
1118 PRE_REG_READ6(int, "ipc",
1119 vki_uint, call, int, first, int, second, int, third,
1120 void *, ptr, long, fifth)
1121
1122 switch (ARG1 /* call */) {
1123 case VKI_SEMOP:
sewardj7eb7c582005-06-23 01:02:53 +00001124 ML_(generic_PRE_sys_semop)( tid, ARG2, ARG5, ARG3 );
sewardja8d8e232005-06-07 20:04:56 +00001125 *flags |= SfMayBlock;
njnc6168192004-11-29 13:54:10 +00001126 break;
1127 case VKI_SEMGET:
1128 break;
1129 case VKI_SEMCTL:
1130 {
sewardjb369c5e2005-03-24 17:52:02 +00001131 UWord arg = deref_Addr( tid, ARG5, "semctl(arg)" );
sewardj7eb7c582005-06-23 01:02:53 +00001132 ML_(generic_PRE_sys_semctl)( tid, ARG2, ARG3, ARG4, arg );
njnc6168192004-11-29 13:54:10 +00001133 break;
1134 }
1135 case VKI_SEMTIMEDOP:
sewardj7eb7c582005-06-23 01:02:53 +00001136 ML_(generic_PRE_sys_semtimedop)( tid, ARG2, ARG5, ARG3, ARG6 );
sewardja8d8e232005-06-07 20:04:56 +00001137 *flags |= SfMayBlock;
njnc6168192004-11-29 13:54:10 +00001138 break;
1139 case VKI_MSGSND:
njncd405ea2005-08-31 02:44:31 +00001140 ML_(linux_PRE_sys_msgsnd)( tid, ARG2, ARG5, ARG3, ARG4 );
sewardja8d8e232005-06-07 20:04:56 +00001141 if ((ARG4 & VKI_IPC_NOWAIT) == 0)
1142 *flags |= SfMayBlock;
njnc6168192004-11-29 13:54:10 +00001143 break;
njnc6168192004-11-29 13:54:10 +00001144 case VKI_MSGRCV:
1145 {
sewardjb369c5e2005-03-24 17:52:02 +00001146 Addr msgp;
1147 Word msgtyp;
njnc6168192004-11-29 13:54:10 +00001148
sewardjb369c5e2005-03-24 17:52:02 +00001149 msgp = deref_Addr( tid,
1150 (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgp),
1151 "msgrcv(msgp)" );
1152 msgtyp = deref_Addr( tid,
1153 (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgtyp),
1154 "msgrcv(msgp)" );
njnc6168192004-11-29 13:54:10 +00001155
njncd405ea2005-08-31 02:44:31 +00001156 ML_(linux_PRE_sys_msgrcv)( tid, ARG2, msgp, ARG3, msgtyp, ARG4 );
njnc6168192004-11-29 13:54:10 +00001157
sewardja8d8e232005-06-07 20:04:56 +00001158 if ((ARG4 & VKI_IPC_NOWAIT) == 0)
1159 *flags |= SfMayBlock;
njnc6168192004-11-29 13:54:10 +00001160 break;
1161 }
1162 case VKI_MSGGET:
1163 break;
1164 case VKI_MSGCTL:
njncd405ea2005-08-31 02:44:31 +00001165 ML_(linux_PRE_sys_msgctl)( tid, ARG2, ARG3, ARG5 );
njnc6168192004-11-29 13:54:10 +00001166 break;
njnc6168192004-11-29 13:54:10 +00001167 case VKI_SHMAT:
sewardja8d8e232005-06-07 20:04:56 +00001168 {
1169 UWord w;
sewardjb369c5e2005-03-24 17:52:02 +00001170 PRE_MEM_WRITE( "shmat(raddr)", ARG4, sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001171 w = ML_(generic_PRE_sys_shmat)( tid, ARG2, ARG5, ARG3 );
sewardja8d8e232005-06-07 20:04:56 +00001172 if (w == 0)
1173 SET_STATUS_Failure( VKI_EINVAL );
1174 else
1175 ARG5 = w;
njnc6168192004-11-29 13:54:10 +00001176 break;
sewardja8d8e232005-06-07 20:04:56 +00001177 }
njnc6168192004-11-29 13:54:10 +00001178 case VKI_SHMDT:
sewardj7eb7c582005-06-23 01:02:53 +00001179 if (!ML_(generic_PRE_sys_shmdt)(tid, ARG5))
sewardja8d8e232005-06-07 20:04:56 +00001180 SET_STATUS_Failure( VKI_EINVAL );
njnc6168192004-11-29 13:54:10 +00001181 break;
1182 case VKI_SHMGET:
1183 break;
1184 case VKI_SHMCTL: /* IPCOP_shmctl */
sewardj7eb7c582005-06-23 01:02:53 +00001185 ML_(generic_PRE_sys_shmctl)( tid, ARG2, ARG3, ARG5 );
njnc6168192004-11-29 13:54:10 +00001186 break;
njnc6168192004-11-29 13:54:10 +00001187 default:
1188 VG_(message)(Vg_DebugMsg, "FATAL: unhandled syscall(ipc) %d", ARG1 );
1189 VG_(core_panic)("... bye!\n");
1190 break; /*NOTREACHED*/
1191 }
1192}
1193
1194POST(sys_ipc)
1195{
sewardja8d8e232005-06-07 20:04:56 +00001196 vg_assert(SUCCESS);
njnc6168192004-11-29 13:54:10 +00001197 switch (ARG1 /* call */) {
1198 case VKI_SEMOP:
1199 case VKI_SEMGET:
1200 break;
1201 case VKI_SEMCTL:
1202 {
sewardjb369c5e2005-03-24 17:52:02 +00001203 UWord arg = deref_Addr( tid, ARG5, "semctl(arg)" );
sewardj7eb7c582005-06-23 01:02:53 +00001204 ML_(generic_PRE_sys_semctl)( tid, ARG2, ARG3, ARG4, arg );
njnc6168192004-11-29 13:54:10 +00001205 break;
1206 }
1207 case VKI_SEMTIMEDOP:
1208 case VKI_MSGSND:
1209 break;
1210 case VKI_MSGRCV:
1211 {
sewardjb369c5e2005-03-24 17:52:02 +00001212 Addr msgp;
1213 Word msgtyp;
1214
1215 msgp = deref_Addr( tid,
1216 (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgp),
1217 "msgrcv(msgp)" );
1218 msgtyp = deref_Addr( tid,
1219 (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgtyp),
1220 "msgrcv(msgp)" );
1221
njncd405ea2005-08-31 02:44:31 +00001222 ML_(linux_POST_sys_msgrcv)( tid, RES, ARG2, msgp, ARG3, msgtyp, ARG4 );
njnc6168192004-11-29 13:54:10 +00001223 break;
1224 }
1225 case VKI_MSGGET:
1226 break;
1227 case VKI_MSGCTL:
njncd405ea2005-08-31 02:44:31 +00001228 ML_(linux_POST_sys_msgctl)( tid, RES, ARG2, ARG3, ARG5 );
njnc6168192004-11-29 13:54:10 +00001229 break;
njnc6168192004-11-29 13:54:10 +00001230 case VKI_SHMAT:
1231 {
njnc6168192004-11-29 13:54:10 +00001232 Addr addr;
1233
1234 /* force readability. before the syscall it is
1235 * indeed uninitialized, as can be seen in
1236 * glibc/sysdeps/unix/sysv/linux/shmat.c */
sewardjb369c5e2005-03-24 17:52:02 +00001237 POST_MEM_WRITE( ARG4, sizeof( Addr ) );
njnc6168192004-11-29 13:54:10 +00001238
1239 addr = deref_Addr ( tid, ARG4, "shmat(addr)" );
1240 if ( addr > 0 ) {
sewardj7eb7c582005-06-23 01:02:53 +00001241 ML_(generic_POST_sys_shmat)( tid, addr, ARG2, ARG5, ARG3 );
njnc6168192004-11-29 13:54:10 +00001242 }
1243 break;
1244 }
1245 case VKI_SHMDT:
sewardj7eb7c582005-06-23 01:02:53 +00001246 ML_(generic_POST_sys_shmdt)( tid, RES, ARG5 );
njnc6168192004-11-29 13:54:10 +00001247 break;
njnc6168192004-11-29 13:54:10 +00001248 case VKI_SHMGET:
1249 break;
1250 case VKI_SHMCTL:
sewardj7eb7c582005-06-23 01:02:53 +00001251 ML_(generic_POST_sys_shmctl)( tid, RES, ARG2, ARG3, ARG5 );
njnc6168192004-11-29 13:54:10 +00001252 break;
njnc6168192004-11-29 13:54:10 +00001253 default:
1254 VG_(message)(Vg_DebugMsg,
1255 "FATAL: unhandled syscall(ipc) %d",
1256 ARG1 );
1257 VG_(core_panic)("... bye!\n");
1258 break; /*NOTREACHED*/
1259 }
1260}
1261
sewardja8d8e232005-06-07 20:04:56 +00001262PRE(old_mmap)
sewardjb5f6f512005-03-10 23:59:00 +00001263{
sewardja8d8e232005-06-07 20:04:56 +00001264 /* struct mmap_arg_struct {
1265 unsigned long addr;
1266 unsigned long len;
1267 unsigned long prot;
1268 unsigned long flags;
1269 unsigned long fd;
1270 unsigned long offset;
1271 }; */
1272 UWord a1, a2, a3, a4, a5, a6;
tom9548a162005-09-30 08:07:53 +00001273 SysRes r;
sewardja8d8e232005-06-07 20:04:56 +00001274
sewardje6d5e722005-06-10 10:27:55 +00001275 UWord* args = (UWord*)ARG1;
1276 PRE_REG_READ1(long, "old_mmap", struct mmap_arg_struct *, args);
1277 PRE_MEM_READ( "old_mmap(args)", (Addr)args, 6*sizeof(UWord) );
sewardja8d8e232005-06-07 20:04:56 +00001278
sewardj45f4e7c2005-09-27 19:20:21 +00001279 a1 = args[1-1];
1280 a2 = args[2-1];
1281 a3 = args[3-1];
1282 a4 = args[4-1];
1283 a5 = args[5-1];
1284 a6 = args[6-1];
sewardja8d8e232005-06-07 20:04:56 +00001285
1286 PRINT("old_mmap ( %p, %llu, %d, %d, %d, %d )",
1287 a1, (ULong)a2, a3, a4, a5, a6 );
1288
sewardj274461d2005-10-02 17:01:41 +00001289 r = ML_(generic_PRE_sys_mmap)( tid, a1, a2, a3, a4, a5, (Off64T)a6 );
tom9548a162005-09-30 08:07:53 +00001290 SET_STATUS_from_SysRes(r);
1291}
sewardja8d8e232005-06-07 20:04:56 +00001292
tom9548a162005-09-30 08:07:53 +00001293PRE(sys_mmap2)
1294{
1295 SysRes r;
sewardja8d8e232005-06-07 20:04:56 +00001296
tom9548a162005-09-30 08:07:53 +00001297 // Exactly like old_mmap() except:
1298 // - all 6 args are passed in regs, rather than in a memory-block.
1299 // - the file offset is specified in pagesize units rather than bytes,
1300 // so that it can be used for files bigger than 2^32 bytes.
1301 PRINT("sys_mmap2 ( %p, %llu, %d, %d, %d, %d )",
1302 ARG1, (ULong)ARG2, ARG3, ARG4, ARG5, ARG6 );
1303 PRE_REG_READ6(long, "mmap2",
1304 unsigned long, start, unsigned long, length,
1305 unsigned long, prot, unsigned long, flags,
1306 unsigned long, fd, unsigned long, offset);
sewardja8d8e232005-06-07 20:04:56 +00001307
sewardj274461d2005-10-02 17:01:41 +00001308 r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5,
1309 VKI_PAGE_SIZE * (Off64T)ARG6 );
tom9548a162005-09-30 08:07:53 +00001310 SET_STATUS_from_SysRes(r);
sewardjb5f6f512005-03-10 23:59:00 +00001311}
sewardja8d8e232005-06-07 20:04:56 +00001312
1313// XXX: lstat64/fstat64/stat64 are generic, but not necessarily
1314// applicable to every architecture -- I think only to 32-bit archs.
1315// We're going to need something like linux/core_os32.h for such
1316// things, eventually, I think. --njn
1317PRE(sys_lstat64)
njnc6168192004-11-29 13:54:10 +00001318{
sewardja8d8e232005-06-07 20:04:56 +00001319 PRINT("sys_lstat64 ( %p(%s), %p )",ARG1,ARG1,ARG2);
1320 PRE_REG_READ2(long, "lstat64", char *, file_name, struct stat64 *, buf);
1321 PRE_MEM_RASCIIZ( "lstat64(file_name)", ARG1 );
1322 PRE_MEM_WRITE( "lstat64(buf)", ARG2, sizeof(struct vki_stat64) );
1323}
sewardjb5f6f512005-03-10 23:59:00 +00001324
sewardja8d8e232005-06-07 20:04:56 +00001325POST(sys_lstat64)
1326{
1327 vg_assert(SUCCESS);
1328 if (RES == 0) {
1329 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
sewardjb5f6f512005-03-10 23:59:00 +00001330 }
njnc6168192004-11-29 13:54:10 +00001331}
1332
sewardja8d8e232005-06-07 20:04:56 +00001333PRE(sys_stat64)
njnc6168192004-11-29 13:54:10 +00001334{
sewardja8d8e232005-06-07 20:04:56 +00001335 PRINT("sys_stat64 ( %p, %p )",ARG1,ARG2);
1336 PRE_REG_READ2(long, "stat64", char *, file_name, struct stat64 *, buf);
1337 PRE_MEM_RASCIIZ( "stat64(file_name)", ARG1 );
1338 PRE_MEM_WRITE( "stat64(buf)", ARG2, sizeof(struct vki_stat64) );
njnc6168192004-11-29 13:54:10 +00001339}
1340
sewardja8d8e232005-06-07 20:04:56 +00001341POST(sys_stat64)
1342{
1343 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
1344}
1345
1346PRE(sys_fstat64)
1347{
1348 PRINT("sys_fstat64 ( %d, %p )",ARG1,ARG2);
1349 PRE_REG_READ2(long, "fstat64", unsigned long, fd, struct stat64 *, buf);
1350 PRE_MEM_WRITE( "fstat64(buf)", ARG2, sizeof(struct vki_stat64) );
1351}
1352
1353POST(sys_fstat64)
1354{
1355 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
1356}
1357
1358PRE(sys_socketcall)
1359{
1360# define ARG2_0 (((UWord*)ARG2)[0])
1361# define ARG2_1 (((UWord*)ARG2)[1])
1362# define ARG2_2 (((UWord*)ARG2)[2])
1363# define ARG2_3 (((UWord*)ARG2)[3])
1364# define ARG2_4 (((UWord*)ARG2)[4])
1365# define ARG2_5 (((UWord*)ARG2)[5])
1366
1367 *flags |= SfMayBlock;
1368 PRINT("sys_socketcall ( %d, %p )",ARG1,ARG2);
1369 PRE_REG_READ2(long, "socketcall", int, call, unsigned long *, args);
1370
1371 switch (ARG1 /* request */) {
1372
1373 case VKI_SYS_SOCKETPAIR:
1374 /* int socketpair(int d, int type, int protocol, int sv[2]); */
1375 PRE_MEM_READ( "socketcall.socketpair(args)", ARG2, 4*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001376 ML_(generic_PRE_sys_socketpair)( tid, ARG2_0, ARG2_1, ARG2_2, ARG2_3 );
sewardja8d8e232005-06-07 20:04:56 +00001377 break;
1378
1379 case VKI_SYS_SOCKET:
1380 /* int socket(int domain, int type, int protocol); */
1381 PRE_MEM_READ( "socketcall.socket(args)", ARG2, 3*sizeof(Addr) );
1382 break;
1383
1384 case VKI_SYS_BIND:
1385 /* int bind(int sockfd, struct sockaddr *my_addr,
1386 int addrlen); */
1387 PRE_MEM_READ( "socketcall.bind(args)", ARG2, 3*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001388 ML_(generic_PRE_sys_bind)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001389 break;
1390
1391 case VKI_SYS_LISTEN:
1392 /* int listen(int s, int backlog); */
1393 PRE_MEM_READ( "socketcall.listen(args)", ARG2, 2*sizeof(Addr) );
1394 break;
1395
1396 case VKI_SYS_ACCEPT: {
1397 /* int accept(int s, struct sockaddr *addr, int *addrlen); */
1398 PRE_MEM_READ( "socketcall.accept(args)", ARG2, 3*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001399 ML_(generic_PRE_sys_accept)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001400 break;
1401 }
1402
1403 case VKI_SYS_SENDTO:
1404 /* int sendto(int s, const void *msg, int len,
1405 unsigned int flags,
1406 const struct sockaddr *to, int tolen); */
1407 PRE_MEM_READ( "socketcall.sendto(args)", ARG2, 6*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001408 ML_(generic_PRE_sys_sendto)( tid, ARG2_0, ARG2_1, ARG2_2,
sewardja8d8e232005-06-07 20:04:56 +00001409 ARG2_3, ARG2_4, ARG2_5 );
1410 break;
1411
1412 case VKI_SYS_SEND:
1413 /* int send(int s, const void *msg, size_t len, int flags); */
1414 PRE_MEM_READ( "socketcall.send(args)", ARG2, 4*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001415 ML_(generic_PRE_sys_send)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001416 break;
1417
1418 case VKI_SYS_RECVFROM:
1419 /* int recvfrom(int s, void *buf, int len, unsigned int flags,
1420 struct sockaddr *from, int *fromlen); */
1421 PRE_MEM_READ( "socketcall.recvfrom(args)", ARG2, 6*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001422 ML_(generic_PRE_sys_recvfrom)( tid, ARG2_0, ARG2_1, ARG2_2,
sewardja8d8e232005-06-07 20:04:56 +00001423 ARG2_3, ARG2_4, ARG2_5 );
1424 break;
1425
1426 case VKI_SYS_RECV:
1427 /* int recv(int s, void *buf, int len, unsigned int flags); */
1428 /* man 2 recv says:
1429 The recv call is normally used only on a connected socket
1430 (see connect(2)) and is identical to recvfrom with a NULL
1431 from parameter.
1432 */
1433 PRE_MEM_READ( "socketcall.recv(args)", ARG2, 4*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001434 ML_(generic_PRE_sys_recv)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001435 break;
1436
1437 case VKI_SYS_CONNECT:
1438 /* int connect(int sockfd,
1439 struct sockaddr *serv_addr, int addrlen ); */
1440 PRE_MEM_READ( "socketcall.connect(args)", ARG2, 3*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001441 ML_(generic_PRE_sys_connect)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001442 break;
1443
1444 case VKI_SYS_SETSOCKOPT:
1445 /* int setsockopt(int s, int level, int optname,
1446 const void *optval, int optlen); */
1447 PRE_MEM_READ( "socketcall.setsockopt(args)", ARG2, 5*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001448 ML_(generic_PRE_sys_setsockopt)( tid, ARG2_0, ARG2_1, ARG2_2,
sewardja8d8e232005-06-07 20:04:56 +00001449 ARG2_3, ARG2_4 );
1450 break;
1451
1452 case VKI_SYS_GETSOCKOPT:
1453 /* int getsockopt(int s, int level, int optname,
1454 void *optval, socklen_t *optlen); */
1455 PRE_MEM_READ( "socketcall.getsockopt(args)", ARG2, 5*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001456 ML_(generic_PRE_sys_getsockopt)( tid, ARG2_0, ARG2_1, ARG2_2,
sewardja8d8e232005-06-07 20:04:56 +00001457 ARG2_3, ARG2_4 );
1458 break;
1459
1460 case VKI_SYS_GETSOCKNAME:
1461 /* int getsockname(int s, struct sockaddr* name, int* namelen) */
1462 PRE_MEM_READ( "socketcall.getsockname(args)", ARG2, 3*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001463 ML_(generic_PRE_sys_getsockname)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001464 break;
1465
1466 case VKI_SYS_GETPEERNAME:
1467 /* int getpeername(int s, struct sockaddr* name, int* namelen) */
1468 PRE_MEM_READ( "socketcall.getpeername(args)", ARG2, 3*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001469 ML_(generic_PRE_sys_getpeername)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001470 break;
1471
1472 case VKI_SYS_SHUTDOWN:
1473 /* int shutdown(int s, int how); */
1474 PRE_MEM_READ( "socketcall.shutdown(args)", ARG2, 2*sizeof(Addr) );
1475 break;
1476
1477 case VKI_SYS_SENDMSG: {
1478 /* int sendmsg(int s, const struct msghdr *msg, int flags); */
1479
1480 /* this causes warnings, and I don't get why. glibc bug?
1481 * (after all it's glibc providing the arguments array)
1482 PRE_MEM_READ( "socketcall.sendmsg(args)", ARG2, 3*sizeof(Addr) );
1483 */
sewardj7eb7c582005-06-23 01:02:53 +00001484 ML_(generic_PRE_sys_sendmsg)( tid, ARG2_0, ARG2_1 );
sewardja8d8e232005-06-07 20:04:56 +00001485 break;
1486 }
1487
1488 case VKI_SYS_RECVMSG: {
1489 /* int recvmsg(int s, struct msghdr *msg, int flags); */
1490
1491 /* this causes warnings, and I don't get why. glibc bug?
1492 * (after all it's glibc providing the arguments array)
1493 PRE_MEM_READ("socketcall.recvmsg(args)", ARG2, 3*sizeof(Addr) );
1494 */
sewardj7eb7c582005-06-23 01:02:53 +00001495 ML_(generic_PRE_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
sewardja8d8e232005-06-07 20:04:56 +00001496 break;
1497 }
1498
1499 default:
1500 VG_(message)(Vg_DebugMsg,"Warning: unhandled socketcall 0x%x",ARG1);
1501 SET_STATUS_Failure( VKI_EINVAL );
1502 break;
1503 }
1504# undef ARG2_0
1505# undef ARG2_1
1506# undef ARG2_2
1507# undef ARG2_3
1508# undef ARG2_4
1509# undef ARG2_5
1510}
1511
1512POST(sys_socketcall)
1513{
1514# define ARG2_0 (((UWord*)ARG2)[0])
1515# define ARG2_1 (((UWord*)ARG2)[1])
1516# define ARG2_2 (((UWord*)ARG2)[2])
1517# define ARG2_3 (((UWord*)ARG2)[3])
1518# define ARG2_4 (((UWord*)ARG2)[4])
1519# define ARG2_5 (((UWord*)ARG2)[5])
1520
1521 SysRes r;
1522 vg_assert(SUCCESS);
1523 switch (ARG1 /* request */) {
1524
1525 case VKI_SYS_SOCKETPAIR:
sewardj7eb7c582005-06-23 01:02:53 +00001526 r = ML_(generic_POST_sys_socketpair)(
sewardja8d8e232005-06-07 20:04:56 +00001527 tid, VG_(mk_SysRes_Success)(RES),
1528 ARG2_0, ARG2_1, ARG2_2, ARG2_3
1529 );
1530 SET_STATUS_from_SysRes(r);
1531 break;
1532
1533 case VKI_SYS_SOCKET:
sewardj7eb7c582005-06-23 01:02:53 +00001534 r = ML_(generic_POST_sys_socket)( tid, VG_(mk_SysRes_Success)(RES) );
sewardja8d8e232005-06-07 20:04:56 +00001535 SET_STATUS_from_SysRes(r);
1536 break;
1537
1538 case VKI_SYS_BIND:
1539 /* int bind(int sockfd, struct sockaddr *my_addr,
1540 int addrlen); */
1541 break;
1542
1543 case VKI_SYS_LISTEN:
1544 /* int listen(int s, int backlog); */
1545 break;
1546
1547 case VKI_SYS_ACCEPT:
1548 /* int accept(int s, struct sockaddr *addr, int *addrlen); */
sewardj7eb7c582005-06-23 01:02:53 +00001549 r = ML_(generic_POST_sys_accept)( tid, VG_(mk_SysRes_Success)(RES),
sewardja8d8e232005-06-07 20:04:56 +00001550 ARG2_0, ARG2_1, ARG2_2 );
1551 SET_STATUS_from_SysRes(r);
1552 break;
1553
1554 case VKI_SYS_SENDTO:
1555 break;
1556
1557 case VKI_SYS_SEND:
1558 break;
1559
1560 case VKI_SYS_RECVFROM:
sewardj7eb7c582005-06-23 01:02:53 +00001561 ML_(generic_POST_sys_recvfrom)( tid, VG_(mk_SysRes_Success)(RES),
sewardja8d8e232005-06-07 20:04:56 +00001562 ARG2_0, ARG2_1, ARG2_2,
1563 ARG2_3, ARG2_4, ARG2_5 );
1564 break;
1565
1566 case VKI_SYS_RECV:
sewardj7eb7c582005-06-23 01:02:53 +00001567 ML_(generic_POST_sys_recv)( tid, RES, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001568 break;
1569
1570 case VKI_SYS_CONNECT:
1571 break;
1572
1573 case VKI_SYS_SETSOCKOPT:
1574 break;
1575
1576 case VKI_SYS_GETSOCKOPT:
sewardj7eb7c582005-06-23 01:02:53 +00001577 ML_(generic_POST_sys_getsockopt)( tid, VG_(mk_SysRes_Success)(RES),
sewardja8d8e232005-06-07 20:04:56 +00001578 ARG2_0, ARG2_1,
1579 ARG2_2, ARG2_3, ARG2_4 );
1580 break;
1581
1582 case VKI_SYS_GETSOCKNAME:
sewardj7eb7c582005-06-23 01:02:53 +00001583 ML_(generic_POST_sys_getsockname)( tid, VG_(mk_SysRes_Success)(RES),
sewardja8d8e232005-06-07 20:04:56 +00001584 ARG2_0, ARG2_1, ARG2_2 );
1585 break;
1586
1587 case VKI_SYS_GETPEERNAME:
sewardj7eb7c582005-06-23 01:02:53 +00001588 ML_(generic_POST_sys_getpeername)( tid, VG_(mk_SysRes_Success)(RES),
sewardja8d8e232005-06-07 20:04:56 +00001589 ARG2_0, ARG2_1, ARG2_2 );
1590 break;
1591
1592 case VKI_SYS_SHUTDOWN:
1593 break;
1594
1595 case VKI_SYS_SENDMSG:
1596 break;
1597
1598 case VKI_SYS_RECVMSG:
sewardj7eb7c582005-06-23 01:02:53 +00001599 ML_(generic_POST_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
sewardja8d8e232005-06-07 20:04:56 +00001600 break;
1601
1602 default:
1603 VG_(message)(Vg_DebugMsg,"FATAL: unhandled socketcall 0x%x",ARG1);
1604 VG_(core_panic)("... bye!\n");
1605 break; /*NOTREACHED*/
1606 }
1607# undef ARG2_0
1608# undef ARG2_1
1609# undef ARG2_2
1610# undef ARG2_3
1611# undef ARG2_4
1612# undef ARG2_5
1613}
1614
sewardj696c5512005-06-08 23:38:32 +00001615/* Convert from non-RT to RT sigset_t's */
1616static
1617void convert_sigset_to_rt(const vki_old_sigset_t *oldset, vki_sigset_t *set)
1618{
1619 VG_(sigemptyset)(set);
1620 set->sig[0] = *oldset;
1621}
1622PRE(sys_sigaction)
1623{
1624 struct vki_sigaction new, old;
1625 struct vki_sigaction *newp, *oldp;
1626
1627 PRINT("sys_sigaction ( %d, %p, %p )", ARG1,ARG2,ARG3);
1628 PRE_REG_READ3(int, "sigaction",
1629 int, signum, const struct old_sigaction *, act,
1630 struct old_sigaction *, oldact);
1631
1632 newp = oldp = NULL;
1633
tomd9cac2f2005-08-07 15:16:59 +00001634 if (ARG2 != 0) {
1635 struct vki_old_sigaction *sa = (struct vki_old_sigaction *)ARG2;
tom9b52a342005-08-08 16:50:16 +00001636 PRE_MEM_READ( "sigaction(act->sa_handler)", (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler));
1637 PRE_MEM_READ( "sigaction(act->sa_mask)", (Addr)&sa->sa_mask, sizeof(sa->sa_mask));
1638 PRE_MEM_READ( "sigaction(act->sa_flags)", (Addr)&sa->sa_flags, sizeof(sa->sa_flags));
sewardj45f4e7c2005-09-27 19:20:21 +00001639 if (ML_(safe_to_deref)(sa,sizeof(sa))
1640 && (sa->sa_flags & VKI_SA_RESTORER))
tom9b52a342005-08-08 16:50:16 +00001641 PRE_MEM_READ( "sigaction(act->sa_restorer)", (Addr)&sa->sa_restorer, sizeof(sa->sa_restorer));
tomd9cac2f2005-08-07 15:16:59 +00001642 }
sewardj696c5512005-06-08 23:38:32 +00001643
1644 if (ARG3 != 0) {
1645 PRE_MEM_WRITE( "sigaction(oldact)", ARG3, sizeof(struct vki_old_sigaction));
1646 oldp = &old;
1647 }
1648
1649 //jrs 20050207: what?! how can this make any sense?
1650 //if (VG_(is_kerror)(SYSRES))
1651 // return;
1652
1653 if (ARG2 != 0) {
1654 struct vki_old_sigaction *oldnew = (struct vki_old_sigaction *)ARG2;
1655
1656 new.ksa_handler = oldnew->ksa_handler;
1657 new.sa_flags = oldnew->sa_flags;
1658 new.sa_restorer = oldnew->sa_restorer;
1659 convert_sigset_to_rt(&oldnew->sa_mask, &new.sa_mask);
1660 newp = &new;
1661 }
1662
1663 SET_STATUS_from_SysRes( VG_(do_sys_sigaction)(ARG1, newp, oldp) );
1664
1665 if (ARG3 != 0 && SUCCESS && RES == 0) {
1666 struct vki_old_sigaction *oldold = (struct vki_old_sigaction *)ARG3;
1667
1668 oldold->ksa_handler = oldp->ksa_handler;
1669 oldold->sa_flags = oldp->sa_flags;
1670 oldold->sa_restorer = oldp->sa_restorer;
1671 oldold->sa_mask = oldp->sa_mask.sig[0];
1672 }
1673}
1674
1675POST(sys_sigaction)
1676{
1677 vg_assert(SUCCESS);
1678 if (RES == 0 && ARG3 != 0)
1679 POST_MEM_WRITE( ARG3, sizeof(struct vki_old_sigaction));
1680}
1681
tomc1369aa2006-02-11 16:26:46 +00001682PRE(sys_vm86old)
1683{
1684 PRINT("sys_vm86old ( %p )", ARG1);
1685 PRE_REG_READ1(int, "vm86old", struct vm86_struct *, info);
1686 PRE_MEM_WRITE( "vm86old(info)", ARG1, sizeof(struct vki_vm86_struct));
1687}
1688
1689POST(sys_vm86old)
1690{
1691 POST_MEM_WRITE( ARG1, sizeof(struct vki_vm86_struct));
1692}
1693
1694PRE(sys_vm86)
1695{
1696 PRINT("sys_vm86 ( %d, %p )", ARG1,ARG2);
1697 PRE_REG_READ2(int, "vm86", unsigned long, fn, struct vm86plus_struct *, v86);
1698 if (ARG1 == VKI_VM86_ENTER || ARG1 == VKI_VM86_ENTER_NO_BYPASS)
1699 PRE_MEM_WRITE( "vm86(v86)", ARG2, sizeof(struct vki_vm86plus_struct));
1700}
1701
1702POST(sys_vm86)
1703{
1704 if (ARG1 == VKI_VM86_ENTER || ARG1 == VKI_VM86_ENTER_NO_BYPASS)
1705 POST_MEM_WRITE( ARG2, sizeof(struct vki_vm86plus_struct));
1706}
1707
sewardjce5a5662005-10-06 03:19:49 +00001708
1709/* ---------------------------------------------------------------
1710 PRE/POST wrappers for x86/Linux-variant specific syscalls
1711 ------------------------------------------------------------ */
1712
1713PRE(sys_syscall223)
1714{
1715 Int err;
1716
1717 /* 223 is used by sys_bproc. If we're not on a declared bproc
1718 variant, fail in the usual way. */
1719
1720 if (!VG_(strstr)(VG_(clo_kernel_variant), "bproc")) {
1721 PRINT("non-existent syscall! (syscall 223)");
1722 PRE_REG_READ0(long, "ni_syscall(223)");
1723 SET_STATUS_Failure( VKI_ENOSYS );
1724 return;
1725 }
1726
1727 err = ML_(linux_variant_PRE_sys_bproc)( ARG1, ARG2, ARG3,
1728 ARG4, ARG5, ARG6 );
1729 if (err) {
1730 SET_STATUS_Failure( err );
1731 return;
1732 }
1733 /* Let it go through. */
1734 *flags |= SfMayBlock; /* who knows? play safe. */
1735}
1736
1737POST(sys_syscall223)
1738{
1739 ML_(linux_variant_POST_sys_bproc)( ARG1, ARG2, ARG3,
1740 ARG4, ARG5, ARG6 );
1741}
1742
sewardj696c5512005-06-08 23:38:32 +00001743#undef PRE
1744#undef POST
1745
nethercote8ff888f2004-11-17 17:11:45 +00001746
1747/* ---------------------------------------------------------------------
1748 The x86/Linux syscall table
1749 ------------------------------------------------------------------ */
1750
sewardje7aa4ae2005-06-09 12:43:42 +00001751/* Add an x86-linux specific wrapper to a syscall table. */
sewardja8d8e232005-06-07 20:04:56 +00001752#define PLAX_(sysno, name) WRAPPER_ENTRY_X_(x86_linux, sysno, name)
1753#define PLAXY(sysno, name) WRAPPER_ENTRY_XY(x86_linux, sysno, name)
1754
nethercote8ff888f2004-11-17 17:11:45 +00001755
nethercote3d5e9102004-11-17 18:22:38 +00001756// This table maps from __NR_xxx syscall numbers (from
1757// linux/include/asm-i386/unistd.h) to the appropriate PRE/POST sys_foo()
1758// wrappers on x86 (as per sys_call_table in linux/arch/i386/kernel/entry.S).
1759//
1760// For those syscalls not handled by Valgrind, the annotation indicate its
1761// arch/OS combination, eg. */* (generic), */Linux (Linux only), ?/?
1762// (unknown).
1763
njnaf839f52005-06-23 03:27:57 +00001764const SyscallTableEntry ML_(syscall_table)[] = {
sewardja8d8e232005-06-07 20:04:56 +00001765//zz // (restart_syscall) // 0
nethercote8ff888f2004-11-17 17:11:45 +00001766 GENX_(__NR_exit, sys_exit), // 1
sewardjb5f6f512005-03-10 23:59:00 +00001767 GENX_(__NR_fork, sys_fork), // 2
nethercote8ff888f2004-11-17 17:11:45 +00001768 GENXY(__NR_read, sys_read), // 3
1769 GENX_(__NR_write, sys_write), // 4
1770
1771 GENXY(__NR_open, sys_open), // 5
1772 GENXY(__NR_close, sys_close), // 6
1773 GENXY(__NR_waitpid, sys_waitpid), // 7
1774 GENXY(__NR_creat, sys_creat), // 8
1775 GENX_(__NR_link, sys_link), // 9
1776
1777 GENX_(__NR_unlink, sys_unlink), // 10
nethercote3d5e9102004-11-17 18:22:38 +00001778 GENX_(__NR_execve, sys_execve), // 11
nethercote8ff888f2004-11-17 17:11:45 +00001779 GENX_(__NR_chdir, sys_chdir), // 12
1780 GENXY(__NR_time, sys_time), // 13
1781 GENX_(__NR_mknod, sys_mknod), // 14
1782
1783 GENX_(__NR_chmod, sys_chmod), // 15
njnefc957c2005-08-26 04:36:10 +00001784//zz LINX_(__NR_lchown, sys_lchown16), // 16
nethercote3d5e9102004-11-17 18:22:38 +00001785 GENX_(__NR_break, sys_ni_syscall), // 17
sewardja8d8e232005-06-07 20:04:56 +00001786//zz // (__NR_oldstat, sys_stat), // 18 (obsolete)
njncd405ea2005-08-31 02:44:31 +00001787 LINX_(__NR_lseek, sys_lseek), // 19
nethercote8ff888f2004-11-17 17:11:45 +00001788
1789 GENX_(__NR_getpid, sys_getpid), // 20
1790 LINX_(__NR_mount, sys_mount), // 21
1791 LINX_(__NR_umount, sys_oldumount), // 22
njna3b67b72005-08-26 04:27:54 +00001792 LINX_(__NR_setuid, sys_setuid16), // 23 ## P
1793 LINX_(__NR_getuid, sys_getuid16), // 24 ## P
sewardja8d8e232005-06-07 20:04:56 +00001794//zz
1795//zz // (__NR_stime, sys_stime), // 25 * (SVr4,SVID,X/OPEN)
sewardj8c257322005-06-08 01:01:48 +00001796 PLAXY(__NR_ptrace, sys_ptrace), // 26
nethercote3d5e9102004-11-17 18:22:38 +00001797 GENX_(__NR_alarm, sys_alarm), // 27
sewardja8d8e232005-06-07 20:04:56 +00001798//zz // (__NR_oldfstat, sys_fstat), // 28 * L -- obsolete
nethercote3d5e9102004-11-17 18:22:38 +00001799 GENX_(__NR_pause, sys_pause), // 29
sewardj8c9ea4e2005-06-08 10:46:56 +00001800
njncd405ea2005-08-31 02:44:31 +00001801 LINX_(__NR_utime, sys_utime), // 30
nethercote3d5e9102004-11-17 18:22:38 +00001802 GENX_(__NR_stty, sys_ni_syscall), // 31
1803 GENX_(__NR_gtty, sys_ni_syscall), // 32
1804 GENX_(__NR_access, sys_access), // 33
sewardj8c9ea4e2005-06-08 10:46:56 +00001805 GENX_(__NR_nice, sys_nice), // 34
1806
nethercote3d5e9102004-11-17 18:22:38 +00001807 GENX_(__NR_ftime, sys_ni_syscall), // 35
sewardj8c9ea4e2005-06-08 10:46:56 +00001808 GENX_(__NR_sync, sys_sync), // 36
njn03f1e582005-03-26 20:08:06 +00001809 GENX_(__NR_kill, sys_kill), // 37
nethercote8ff888f2004-11-17 17:11:45 +00001810 GENX_(__NR_rename, sys_rename), // 38
1811 GENX_(__NR_mkdir, sys_mkdir), // 39
sewardj78b50e42005-06-08 01:47:28 +00001812
1813 GENX_(__NR_rmdir, sys_rmdir), // 40
nethercote8ff888f2004-11-17 17:11:45 +00001814 GENXY(__NR_dup, sys_dup), // 41
njncd405ea2005-08-31 02:44:31 +00001815 LINXY(__NR_pipe, sys_pipe), // 42
sewardj78b50e42005-06-08 01:47:28 +00001816 GENXY(__NR_times, sys_times), // 43
nethercote3d5e9102004-11-17 18:22:38 +00001817 GENX_(__NR_prof, sys_ni_syscall), // 44
sewardja8d8e232005-06-07 20:04:56 +00001818//zz
nethercote3d5e9102004-11-17 18:22:38 +00001819 GENX_(__NR_brk, sys_brk), // 45
njna3b67b72005-08-26 04:27:54 +00001820 LINX_(__NR_setgid, sys_setgid16), // 46
1821 LINX_(__NR_getgid, sys_getgid16), // 47
sewardja8d8e232005-06-07 20:04:56 +00001822//zz // (__NR_signal, sys_signal), // 48 */* (ANSI C)
njna3b67b72005-08-26 04:27:54 +00001823 LINX_(__NR_geteuid, sys_geteuid16), // 49
sewardj696c5512005-06-08 23:38:32 +00001824
njna3b67b72005-08-26 04:27:54 +00001825 LINX_(__NR_getegid, sys_getegid16), // 50
sewardj696c5512005-06-08 23:38:32 +00001826 GENX_(__NR_acct, sys_acct), // 51
1827 LINX_(__NR_umount2, sys_umount), // 52
nethercote3d5e9102004-11-17 18:22:38 +00001828 GENX_(__NR_lock, sys_ni_syscall), // 53
1829 GENXY(__NR_ioctl, sys_ioctl), // 54
sewardj696c5512005-06-08 23:38:32 +00001830
1831 GENXY(__NR_fcntl, sys_fcntl), // 55
nethercote3d5e9102004-11-17 18:22:38 +00001832 GENX_(__NR_mpx, sys_ni_syscall), // 56
sewardj696c5512005-06-08 23:38:32 +00001833 GENX_(__NR_setpgid, sys_setpgid), // 57
nethercote3d5e9102004-11-17 18:22:38 +00001834 GENX_(__NR_ulimit, sys_ni_syscall), // 58
sewardja8d8e232005-06-07 20:04:56 +00001835//zz // (__NR_oldolduname, sys_olduname), // 59 Linux -- obsolete
1836//zz
sewardj78b50e42005-06-08 01:47:28 +00001837 GENX_(__NR_umask, sys_umask), // 60
sewardj696c5512005-06-08 23:38:32 +00001838 GENX_(__NR_chroot, sys_chroot), // 61
sewardja8d8e232005-06-07 20:04:56 +00001839//zz // (__NR_ustat, sys_ustat) // 62 SVr4 -- deprecated
nethercote8ff888f2004-11-17 17:11:45 +00001840 GENXY(__NR_dup2, sys_dup2), // 63
sewardj1d887112005-05-30 21:44:08 +00001841 GENX_(__NR_getppid, sys_getppid), // 64
sewardj78b50e42005-06-08 01:47:28 +00001842
1843 GENX_(__NR_getpgrp, sys_getpgrp), // 65
sewardj696c5512005-06-08 23:38:32 +00001844 GENX_(__NR_setsid, sys_setsid), // 66
1845 PLAXY(__NR_sigaction, sys_sigaction), // 67
sewardja8d8e232005-06-07 20:04:56 +00001846//zz // (__NR_sgetmask, sys_sgetmask), // 68 */* (ANSI C)
1847//zz // (__NR_ssetmask, sys_ssetmask), // 69 */* (ANSI C)
1848//zz
njna3b67b72005-08-26 04:27:54 +00001849 LINX_(__NR_setreuid, sys_setreuid16), // 70
1850 LINX_(__NR_setregid, sys_setregid16), // 71
sewardja8d8e232005-06-07 20:04:56 +00001851//zz GENX_(__NR_sigsuspend, sys_sigsuspend), // 72
njncd405ea2005-08-31 02:44:31 +00001852 LINXY(__NR_sigpending, sys_sigpending), // 73
sewardja8d8e232005-06-07 20:04:56 +00001853//zz // (__NR_sethostname, sys_sethostname), // 74 */*
1854//zz
nethercote3d5e9102004-11-17 18:22:38 +00001855 GENX_(__NR_setrlimit, sys_setrlimit), // 75
sewardj696c5512005-06-08 23:38:32 +00001856 GENXY(__NR_getrlimit, sys_old_getrlimit), // 76
1857 GENXY(__NR_getrusage, sys_getrusage), // 77
nethercote3d5e9102004-11-17 18:22:38 +00001858 GENXY(__NR_gettimeofday, sys_gettimeofday), // 78
sewardj696c5512005-06-08 23:38:32 +00001859 GENX_(__NR_settimeofday, sys_settimeofday), // 79
1860
njna3b67b72005-08-26 04:27:54 +00001861 LINXY(__NR_getgroups, sys_getgroups16), // 80
1862 LINX_(__NR_setgroups, sys_setgroups16), // 81
sewardj696c5512005-06-08 23:38:32 +00001863 PLAX_(__NR_select, old_select), // 82
sewardj78b50e42005-06-08 01:47:28 +00001864 GENX_(__NR_symlink, sys_symlink), // 83
sewardja8d8e232005-06-07 20:04:56 +00001865//zz // (__NR_oldlstat, sys_lstat), // 84 -- obsolete
1866//zz
rjwalsh17d85302004-11-18 22:56:09 +00001867 GENX_(__NR_readlink, sys_readlink), // 85
sewardja8d8e232005-06-07 20:04:56 +00001868//zz // (__NR_uselib, sys_uselib), // 86 */Linux
1869//zz // (__NR_swapon, sys_swapon), // 87 */Linux
1870//zz // (__NR_reboot, sys_reboot), // 88 */Linux
1871//zz // (__NR_readdir, old_readdir), // 89 -- superseded
1872//zz
1873 PLAX_(__NR_mmap, old_mmap), // 90
nethercote8ff888f2004-11-17 17:11:45 +00001874 GENXY(__NR_munmap, sys_munmap), // 91
sewardj696c5512005-06-08 23:38:32 +00001875 GENX_(__NR_truncate, sys_truncate), // 92
sewardj8c257322005-06-08 01:01:48 +00001876 GENX_(__NR_ftruncate, sys_ftruncate), // 93
sewardj696c5512005-06-08 23:38:32 +00001877 GENX_(__NR_fchmod, sys_fchmod), // 94
1878
njnefc957c2005-08-26 04:36:10 +00001879 LINX_(__NR_fchown, sys_fchown16), // 95
sewardj696c5512005-06-08 23:38:32 +00001880 GENX_(__NR_getpriority, sys_getpriority), // 96
1881 GENX_(__NR_setpriority, sys_setpriority), // 97
nethercote3d5e9102004-11-17 18:22:38 +00001882 GENX_(__NR_profil, sys_ni_syscall), // 98
sewardj696c5512005-06-08 23:38:32 +00001883 GENXY(__NR_statfs, sys_statfs), // 99
1884
1885 GENXY(__NR_fstatfs, sys_fstatfs), // 100
1886 LINX_(__NR_ioperm, sys_ioperm), // 101
sewardja8d8e232005-06-07 20:04:56 +00001887 PLAXY(__NR_socketcall, sys_socketcall), // 102 x86/Linux-only
sewardj696c5512005-06-08 23:38:32 +00001888 LINXY(__NR_syslog, sys_syslog), // 103
1889 GENXY(__NR_setitimer, sys_setitimer), // 104
1890
1891 GENXY(__NR_getitimer, sys_getitimer), // 105
1892 GENXY(__NR_stat, sys_newstat), // 106
1893 GENXY(__NR_lstat, sys_newlstat), // 107
1894 GENXY(__NR_fstat, sys_newfstat), // 108
sewardja8d8e232005-06-07 20:04:56 +00001895//zz // (__NR_olduname, sys_uname), // 109 -- obsolete
1896//zz
sewardj696c5512005-06-08 23:38:32 +00001897 GENX_(__NR_iopl, sys_iopl), // 110
1898 LINX_(__NR_vhangup, sys_vhangup), // 111
nethercote3d5e9102004-11-17 18:22:38 +00001899 GENX_(__NR_idle, sys_ni_syscall), // 112
tomc1369aa2006-02-11 16:26:46 +00001900 PLAXY(__NR_vm86old, sys_vm86old), // 113 x86/Linux-only
nethercote3d5e9102004-11-17 18:22:38 +00001901 GENXY(__NR_wait4, sys_wait4), // 114
sewardja8d8e232005-06-07 20:04:56 +00001902//zz
1903//zz // (__NR_swapoff, sys_swapoff), // 115 */Linux
sewardj696c5512005-06-08 23:38:32 +00001904 LINXY(__NR_sysinfo, sys_sysinfo), // 116
njnc6168192004-11-29 13:54:10 +00001905 PLAXY(__NR_ipc, sys_ipc), // 117
sewardj78b50e42005-06-08 01:47:28 +00001906 GENX_(__NR_fsync, sys_fsync), // 118
sewardjb5f6f512005-03-10 23:59:00 +00001907 PLAX_(__NR_sigreturn, sys_sigreturn), // 119 ?/Linux
nethercote8ff888f2004-11-17 17:11:45 +00001908
nethercote3d5e9102004-11-17 18:22:38 +00001909 PLAX_(__NR_clone, sys_clone), // 120
sewardja8d8e232005-06-07 20:04:56 +00001910//zz // (__NR_setdomainname, sys_setdomainname), // 121 */*(?)
nethercote3d5e9102004-11-17 18:22:38 +00001911 GENXY(__NR_uname, sys_newuname), // 122
1912 PLAX_(__NR_modify_ldt, sys_modify_ldt), // 123
sewardja8d8e232005-06-07 20:04:56 +00001913//zz LINXY(__NR_adjtimex, sys_adjtimex), // 124
1914//zz
nethercote3d5e9102004-11-17 18:22:38 +00001915 GENXY(__NR_mprotect, sys_mprotect), // 125
njncd405ea2005-08-31 02:44:31 +00001916 LINXY(__NR_sigprocmask, sys_sigprocmask), // 126
sewardja8d8e232005-06-07 20:04:56 +00001917//zz // Nb: create_module() was removed 2.4-->2.6
nethercote3d5e9102004-11-17 18:22:38 +00001918 GENX_(__NR_create_module, sys_ni_syscall), // 127
sewardj696c5512005-06-08 23:38:32 +00001919 GENX_(__NR_init_module, sys_init_module), // 128
sewardja8d8e232005-06-07 20:04:56 +00001920//zz // (__NR_delete_module, sys_delete_module), // 129 (*/Linux)?
1921//zz
1922//zz // Nb: get_kernel_syms() was removed 2.4-->2.6
nethercote3d5e9102004-11-17 18:22:38 +00001923 GENX_(__NR_get_kernel_syms, sys_ni_syscall), // 130
njncd405ea2005-08-31 02:44:31 +00001924 LINX_(__NR_quotactl, sys_quotactl), // 131
sewardj696c5512005-06-08 23:38:32 +00001925 GENX_(__NR_getpgid, sys_getpgid), // 132
1926 GENX_(__NR_fchdir, sys_fchdir), // 133
sewardja8d8e232005-06-07 20:04:56 +00001927//zz // (__NR_bdflush, sys_bdflush), // 134 */Linux
1928//zz
1929//zz // (__NR_sysfs, sys_sysfs), // 135 SVr4
sewardj696c5512005-06-08 23:38:32 +00001930 LINX_(__NR_personality, sys_personality), // 136
nethercote3d5e9102004-11-17 18:22:38 +00001931 GENX_(__NR_afs_syscall, sys_ni_syscall), // 137
sewardj696c5512005-06-08 23:38:32 +00001932 LINX_(__NR_setfsuid, sys_setfsuid16), // 138
1933 LINX_(__NR_setfsgid, sys_setfsgid16), // 139
1934
nethercote8ff888f2004-11-17 17:11:45 +00001935 LINXY(__NR__llseek, sys_llseek), // 140
sewardj78b50e42005-06-08 01:47:28 +00001936 GENXY(__NR_getdents, sys_getdents), // 141
nethercote3d5e9102004-11-17 18:22:38 +00001937 GENX_(__NR__newselect, sys_select), // 142
sewardj696c5512005-06-08 23:38:32 +00001938 GENX_(__NR_flock, sys_flock), // 143
1939 GENX_(__NR_msync, sys_msync), // 144
1940
nethercote3d5e9102004-11-17 18:22:38 +00001941 GENXY(__NR_readv, sys_readv), // 145
1942 GENX_(__NR_writev, sys_writev), // 146
sewardj696c5512005-06-08 23:38:32 +00001943 GENX_(__NR_getsid, sys_getsid), // 147
1944 GENX_(__NR_fdatasync, sys_fdatasync), // 148
nethercote8ff888f2004-11-17 17:11:45 +00001945 LINXY(__NR__sysctl, sys_sysctl), // 149
sewardj696c5512005-06-08 23:38:32 +00001946
1947 GENX_(__NR_mlock, sys_mlock), // 150
1948 GENX_(__NR_munlock, sys_munlock), // 151
1949 GENX_(__NR_mlockall, sys_mlockall), // 152
njncd405ea2005-08-31 02:44:31 +00001950 LINX_(__NR_munlockall, sys_munlockall), // 153
njnb2480c92005-08-30 02:17:23 +00001951 LINXY(__NR_sched_setparam, sys_sched_setparam), // 154
sewardje6d5e722005-06-10 10:27:55 +00001952
njnb2480c92005-08-30 02:17:23 +00001953 LINXY(__NR_sched_getparam, sys_sched_getparam), // 155
1954 LINX_(__NR_sched_setscheduler, sys_sched_setscheduler), // 156
1955 LINX_(__NR_sched_getscheduler, sys_sched_getscheduler), // 157
1956 LINX_(__NR_sched_yield, sys_sched_yield), // 158
1957 LINX_(__NR_sched_get_priority_max, sys_sched_get_priority_max),// 159
sewardj78b50e42005-06-08 01:47:28 +00001958
njnb2480c92005-08-30 02:17:23 +00001959 LINX_(__NR_sched_get_priority_min, sys_sched_get_priority_min),// 160
1960//zz //LINX?(__NR_sched_rr_get_interval, sys_sched_rr_get_interval), // 161 */*
nethercote8ff888f2004-11-17 17:11:45 +00001961 GENXY(__NR_nanosleep, sys_nanosleep), // 162
1962 GENX_(__NR_mremap, sys_mremap), // 163
sewardje6d5e722005-06-10 10:27:55 +00001963 LINX_(__NR_setresuid, sys_setresuid16), // 164
1964
1965 LINXY(__NR_getresuid, sys_getresuid16), // 165
tomc1369aa2006-02-11 16:26:46 +00001966 PLAXY(__NR_vm86, sys_vm86), // 166 x86/Linux-only
nethercote3d5e9102004-11-17 18:22:38 +00001967 GENX_(__NR_query_module, sys_ni_syscall), // 167
1968 GENXY(__NR_poll, sys_poll), // 168
sewardja8d8e232005-06-07 20:04:56 +00001969//zz // (__NR_nfsservctl, sys_nfsservctl), // 169 */Linux
1970//zz
sewardje6d5e722005-06-10 10:27:55 +00001971 LINX_(__NR_setresgid, sys_setresgid16), // 170
1972 LINXY(__NR_getresgid, sys_getresgid16), // 171
1973 LINX_(__NR_prctl, sys_prctl), // 172
sewardjd571aff2005-03-15 14:47:30 +00001974 PLAX_(__NR_rt_sigreturn, sys_rt_sigreturn), // 173 x86/Linux only?
njncd405ea2005-08-31 02:44:31 +00001975 LINXY(__NR_rt_sigaction, sys_rt_sigaction), // 174
nethercote8ff888f2004-11-17 17:11:45 +00001976
njncd405ea2005-08-31 02:44:31 +00001977 LINXY(__NR_rt_sigprocmask, sys_rt_sigprocmask), // 175
1978 LINXY(__NR_rt_sigpending, sys_rt_sigpending), // 176
1979 LINXY(__NR_rt_sigtimedwait, sys_rt_sigtimedwait),// 177
1980 LINXY(__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo),// 178
1981 LINX_(__NR_rt_sigsuspend, sys_rt_sigsuspend), // 179
sewardje6d5e722005-06-10 10:27:55 +00001982
1983 GENXY(__NR_pread64, sys_pread64), // 180
1984 GENX_(__NR_pwrite64, sys_pwrite64), // 181
njnefc957c2005-08-26 04:36:10 +00001985 LINX_(__NR_chown, sys_chown16), // 182
nethercote3d5e9102004-11-17 18:22:38 +00001986 GENXY(__NR_getcwd, sys_getcwd), // 183
njn9fe7b122005-08-26 04:03:04 +00001987 LINXY(__NR_capget, sys_capget), // 184
sewardje6d5e722005-06-10 10:27:55 +00001988
njn9fe7b122005-08-26 04:03:04 +00001989 LINX_(__NR_capset, sys_capset), // 185
nethercote3d5e9102004-11-17 18:22:38 +00001990 GENXY(__NR_sigaltstack, sys_sigaltstack), // 186
sewardje6d5e722005-06-10 10:27:55 +00001991 LINXY(__NR_sendfile, sys_sendfile), // 187
1992 GENXY(__NR_getpmsg, sys_getpmsg), // 188
1993 GENX_(__NR_putpmsg, sys_putpmsg), // 189
nethercote8ff888f2004-11-17 17:11:45 +00001994
sewardjc93d7b62005-03-12 20:45:56 +00001995 // Nb: we treat vfork as fork
1996 GENX_(__NR_vfork, sys_fork), // 190
nethercote3d5e9102004-11-17 18:22:38 +00001997 GENXY(__NR_ugetrlimit, sys_getrlimit), // 191
tom9548a162005-09-30 08:07:53 +00001998 PLAX_(__NR_mmap2, sys_mmap2), // 192
sewardje6d5e722005-06-10 10:27:55 +00001999 GENX_(__NR_truncate64, sys_truncate64), // 193
2000 GENX_(__NR_ftruncate64, sys_ftruncate64), // 194
2001
sewardja8d8e232005-06-07 20:04:56 +00002002 PLAXY(__NR_stat64, sys_stat64), // 195
2003 PLAXY(__NR_lstat64, sys_lstat64), // 196
2004 PLAXY(__NR_fstat64, sys_fstat64), // 197
sewardje6d5e722005-06-10 10:27:55 +00002005 GENX_(__NR_lchown32, sys_lchown), // 198
nethercote8ff888f2004-11-17 17:11:45 +00002006 GENX_(__NR_getuid32, sys_getuid), // 199
sewardj78b50e42005-06-08 01:47:28 +00002007
2008 GENX_(__NR_getgid32, sys_getgid), // 200
nethercote8ff888f2004-11-17 17:11:45 +00002009 GENX_(__NR_geteuid32, sys_geteuid), // 201
sewardj78b50e42005-06-08 01:47:28 +00002010 GENX_(__NR_getegid32, sys_getegid), // 202
sewardje6d5e722005-06-10 10:27:55 +00002011 GENX_(__NR_setreuid32, sys_setreuid), // 203
2012 GENX_(__NR_setregid32, sys_setregid), // 204
sewardj78b50e42005-06-08 01:47:28 +00002013
2014 GENXY(__NR_getgroups32, sys_getgroups), // 205
sewardje6d5e722005-06-10 10:27:55 +00002015 GENX_(__NR_setgroups32, sys_setgroups), // 206
2016 GENX_(__NR_fchown32, sys_fchown), // 207
2017 LINX_(__NR_setresuid32, sys_setresuid), // 208
sewardj78b50e42005-06-08 01:47:28 +00002018 LINXY(__NR_getresuid32, sys_getresuid), // 209
2019
sewardje6d5e722005-06-10 10:27:55 +00002020 LINX_(__NR_setresgid32, sys_setresgid), // 210
sewardj78b50e42005-06-08 01:47:28 +00002021 LINXY(__NR_getresgid32, sys_getresgid), // 211
sewardje6d5e722005-06-10 10:27:55 +00002022 GENX_(__NR_chown32, sys_chown), // 212
2023 GENX_(__NR_setuid32, sys_setuid), // 213
2024 GENX_(__NR_setgid32, sys_setgid), // 214
2025
2026 LINX_(__NR_setfsuid32, sys_setfsuid), // 215
2027 LINX_(__NR_setfsgid32, sys_setfsgid), // 216
sewardja8d8e232005-06-07 20:04:56 +00002028//zz // (__NR_pivot_root, sys_pivot_root), // 217 */Linux
sewardje6d5e722005-06-10 10:27:55 +00002029 GENXY(__NR_mincore, sys_mincore), // 218
nethercote3d5e9102004-11-17 18:22:38 +00002030 GENX_(__NR_madvise, sys_madvise), // 219
nethercote8ff888f2004-11-17 17:11:45 +00002031
nethercote3d5e9102004-11-17 18:22:38 +00002032 GENXY(__NR_getdents64, sys_getdents64), // 220
2033 GENXY(__NR_fcntl64, sys_fcntl64), // 221
2034 GENX_(222, sys_ni_syscall), // 222
sewardjce5a5662005-10-06 03:19:49 +00002035 PLAXY(223, sys_syscall223), // 223 // sys_bproc?
sewardj8c257322005-06-08 01:01:48 +00002036 LINX_(__NR_gettid, sys_gettid), // 224
2037
sewardja8d8e232005-06-07 20:04:56 +00002038//zz // (__NR_readahead, sys_readahead), // 225 */(Linux?)
njn65ccc502005-08-30 01:53:54 +00002039 LINX_(__NR_setxattr, sys_setxattr), // 226
2040 LINX_(__NR_lsetxattr, sys_lsetxattr), // 227
2041 LINX_(__NR_fsetxattr, sys_fsetxattr), // 228
2042 LINXY(__NR_getxattr, sys_getxattr), // 229
sewardje6d5e722005-06-10 10:27:55 +00002043
njn65ccc502005-08-30 01:53:54 +00002044 LINXY(__NR_lgetxattr, sys_lgetxattr), // 230
2045 LINXY(__NR_fgetxattr, sys_fgetxattr), // 231
2046 LINXY(__NR_listxattr, sys_listxattr), // 232
2047 LINXY(__NR_llistxattr, sys_llistxattr), // 233
2048 LINXY(__NR_flistxattr, sys_flistxattr), // 234
sewardje6d5e722005-06-10 10:27:55 +00002049
njn65ccc502005-08-30 01:53:54 +00002050 LINX_(__NR_removexattr, sys_removexattr), // 235
2051 LINX_(__NR_lremovexattr, sys_lremovexattr), // 236
2052 LINX_(__NR_fremovexattr, sys_fremovexattr), // 237
sewardja8d8e232005-06-07 20:04:56 +00002053//zz LINX_(__NR_tkill, sys_tkill), // 238 */Linux
sewardje6d5e722005-06-10 10:27:55 +00002054 LINXY(__NR_sendfile64, sys_sendfile64), // 239
2055
sewardjbc22cf72005-06-08 00:02:49 +00002056 LINXY(__NR_futex, sys_futex), // 240
njnb2480c92005-08-30 02:17:23 +00002057 LINX_(__NR_sched_setaffinity, sys_sched_setaffinity), // 241
2058 LINXY(__NR_sched_getaffinity, sys_sched_getaffinity), // 242
sewardjbc22cf72005-06-08 00:02:49 +00002059 PLAX_(__NR_set_thread_area, sys_set_thread_area), // 243
sewardje6d5e722005-06-10 10:27:55 +00002060 PLAX_(__NR_get_thread_area, sys_get_thread_area), // 244
2061
sewardj45f4e7c2005-09-27 19:20:21 +00002062 LINXY(__NR_io_setup, sys_io_setup), // 245
sewardje6d5e722005-06-10 10:27:55 +00002063 LINX_(__NR_io_destroy, sys_io_destroy), // 246
2064 LINXY(__NR_io_getevents, sys_io_getevents), // 247
2065 LINX_(__NR_io_submit, sys_io_submit), // 248
2066 LINXY(__NR_io_cancel, sys_io_cancel), // 249
2067
tom72440832005-06-15 10:31:10 +00002068 LINX_(__NR_fadvise64, sys_fadvise64), // 250 */(Linux?)
nethercote3d5e9102004-11-17 18:22:38 +00002069 GENX_(251, sys_ni_syscall), // 251
sewardjb5f6f512005-03-10 23:59:00 +00002070 LINX_(__NR_exit_group, sys_exit_group), // 252
sewardje6d5e722005-06-10 10:27:55 +00002071 GENXY(__NR_lookup_dcookie, sys_lookup_dcookie), // 253
2072 LINXY(__NR_epoll_create, sys_epoll_create), // 254
2073
2074 LINX_(__NR_epoll_ctl, sys_epoll_ctl), // 255
2075 LINXY(__NR_epoll_wait, sys_epoll_wait), // 256
sewardja8d8e232005-06-07 20:04:56 +00002076//zz // (__NR_remap_file_pages, sys_remap_file_pages), // 257 */Linux
sewardjbc22cf72005-06-08 00:02:49 +00002077 LINX_(__NR_set_tid_address, sys_set_tid_address), // 258
njn424c0562005-08-26 03:54:30 +00002078 LINXY(__NR_timer_create, sys_timer_create), // 259
sewardje6d5e722005-06-10 10:27:55 +00002079
njn424c0562005-08-26 03:54:30 +00002080 LINXY(__NR_timer_settime, sys_timer_settime), // (timer_create+1)
2081 LINXY(__NR_timer_gettime, sys_timer_gettime), // (timer_create+2)
2082 LINX_(__NR_timer_getoverrun, sys_timer_getoverrun),//(timer_create+3)
2083 LINX_(__NR_timer_delete, sys_timer_delete), // (timer_create+4)
njn1588bc02005-08-26 03:49:43 +00002084 LINX_(__NR_clock_settime, sys_clock_settime), // (timer_create+5)
sewardje6d5e722005-06-10 10:27:55 +00002085
njn1588bc02005-08-26 03:49:43 +00002086 LINXY(__NR_clock_gettime, sys_clock_gettime), // (timer_create+6)
2087 LINXY(__NR_clock_getres, sys_clock_getres), // (timer_create+7)
2088 LINXY(__NR_clock_nanosleep, sys_clock_nanosleep),// (timer_create+8) */*
sewardje6d5e722005-06-10 10:27:55 +00002089 GENXY(__NR_statfs64, sys_statfs64), // 268
2090 GENXY(__NR_fstatfs64, sys_fstatfs64), // 269
2091
sewardjbc22cf72005-06-08 00:02:49 +00002092 LINX_(__NR_tgkill, sys_tgkill), // 270 */Linux
sewardje6d5e722005-06-10 10:27:55 +00002093 GENX_(__NR_utimes, sys_utimes), // 271
tom72440832005-06-15 10:31:10 +00002094 LINX_(__NR_fadvise64_64, sys_fadvise64_64), // 272 */(Linux?)
nethercote3d5e9102004-11-17 18:22:38 +00002095 GENX_(__NR_vserver, sys_ni_syscall), // 273
tom70a5cb02005-10-20 17:00:23 +00002096 LINX_(__NR_mbind, sys_mbind), // 274 ?/?
2097
tom2af58f22005-07-22 15:04:14 +00002098 LINXY(__NR_get_mempolicy, sys_get_mempolicy), // 275 ?/?
2099 LINX_(__NR_set_mempolicy, sys_set_mempolicy), // 276 ?/?
njn4279a882005-08-26 03:43:28 +00002100 LINXY(__NR_mq_open, sys_mq_open), // 277
2101 LINX_(__NR_mq_unlink, sys_mq_unlink), // (mq_open+1)
2102 LINX_(__NR_mq_timedsend, sys_mq_timedsend), // (mq_open+2)
sewardj8c9ea4e2005-06-08 10:46:56 +00002103
njn4279a882005-08-26 03:43:28 +00002104 LINXY(__NR_mq_timedreceive, sys_mq_timedreceive),// (mq_open+3)
2105 LINX_(__NR_mq_notify, sys_mq_notify), // (mq_open+4)
2106 LINXY(__NR_mq_getsetattr, sys_mq_getsetattr), // (mq_open+5)
nethercote8ff888f2004-11-17 17:11:45 +00002107 GENX_(__NR_sys_kexec_load, sys_ni_syscall), // 283
njncd405ea2005-08-31 02:44:31 +00002108 LINXY(__NR_waitid, sys_waitid), // 284
tom0bcaf2a2005-07-25 15:21:41 +00002109
2110 GENX_(285, sys_ni_syscall), // 285
2111// LINX_(__NR_add_key, sys_add_key), // 286
2112// LINX_(__NR_request_key, sys_request_key), // 287
2113// LINXY(__NR_keyctl, sys_keyctl), // 288
2114// LINX_(__NR_ioprio_set, sys_ioprio_set), // 289
2115
2116// LINX_(__NR_ioprio_get, sys_ioprio_get), // 290
2117 LINX_(__NR_inotify_init, sys_inotify_init), // 291
2118 LINX_(__NR_inotify_add_watch, sys_inotify_add_watch), // 292
2119 LINX_(__NR_inotify_rm_watch, sys_inotify_rm_watch), // 293
nethercote8ff888f2004-11-17 17:11:45 +00002120};
2121
njnaf839f52005-06-23 03:27:57 +00002122const UInt ML_(syscall_table_size) =
2123 sizeof(ML_(syscall_table)) / sizeof(ML_(syscall_table)[0]);
nethercote8ff888f2004-11-17 17:11:45 +00002124
nethercote41c75da2004-10-18 15:34:14 +00002125/*--------------------------------------------------------------------*/
2126/*--- end ---*/
2127/*--------------------------------------------------------------------*/