blob: 8f1ecf51194450b852937d91b03ce0b269d2df1b [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);
sewardjce5a5662005-10-06 03:19:49 +0000775DECL_TEMPLATE(x86_linux, sys_syscall223);
nethercote8ff888f2004-11-17 17:11:45 +0000776
sewardj696c5512005-06-08 23:38:32 +0000777PRE(old_select)
778{
779 /* struct sel_arg_struct {
780 unsigned long n;
781 fd_set *inp, *outp, *exp;
782 struct timeval *tvp;
783 };
784 */
785 PRE_REG_READ1(long, "old_select", struct sel_arg_struct *, args);
786 PRE_MEM_READ( "old_select(args)", ARG1, 5*sizeof(UWord) );
787 *flags |= SfMayBlock;
788 {
789 UInt* arg_struct = (UInt*)ARG1;
790 UInt a1, a2, a3, a4, a5;
791
792 a1 = arg_struct[0];
793 a2 = arg_struct[1];
794 a3 = arg_struct[2];
795 a4 = arg_struct[3];
796 a5 = arg_struct[4];
797
798 PRINT("old_select ( %d, %p, %p, %p, %p )", a1,a2,a3,a4,a5);
799 if (a2 != (Addr)NULL)
800 PRE_MEM_READ( "old_select(readfds)", a2, a1/8 /* __FD_SETSIZE/8 */ );
801 if (a3 != (Addr)NULL)
802 PRE_MEM_READ( "old_select(writefds)", a3, a1/8 /* __FD_SETSIZE/8 */ );
803 if (a4 != (Addr)NULL)
804 PRE_MEM_READ( "old_select(exceptfds)", a4, a1/8 /* __FD_SETSIZE/8 */ );
805 if (a5 != (Addr)NULL)
806 PRE_MEM_READ( "old_select(timeout)", a5, sizeof(struct vki_timeval) );
807 }
808}
nethercote3d5e9102004-11-17 18:22:38 +0000809
sewardja8d8e232005-06-07 20:04:56 +0000810PRE(sys_clone)
nethercote3d5e9102004-11-17 18:22:38 +0000811{
sewardjb5f6f512005-03-10 23:59:00 +0000812 UInt cloneflags;
nethercote3d5e9102004-11-17 18:22:38 +0000813
sewardjb5f6f512005-03-10 23:59:00 +0000814 PRINT("sys_clone ( %x, %p, %p, %p, %p )",ARG1,ARG2,ARG3,ARG4,ARG5);
815 PRE_REG_READ5(int, "clone",
816 unsigned long, flags,
817 void *, child_stack,
818 int *, parent_tidptr,
819 vki_modify_ldt_t *, tlsinfo,
820 int *, child_tidptr);
821
822 if (ARG1 & VKI_CLONE_PARENT_SETTID) {
823 PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
sewardj45f4e7c2005-09-27 19:20:21 +0000824 if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int),
825 VKI_PROT_WRITE)) {
sewardja8d8e232005-06-07 20:04:56 +0000826 SET_STATUS_Failure( VKI_EFAULT );
sewardjb5f6f512005-03-10 23:59:00 +0000827 return;
828 }
nethercote3d5e9102004-11-17 18:22:38 +0000829 }
sewardjb5f6f512005-03-10 23:59:00 +0000830 if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
831 PRE_MEM_WRITE("clone(child_tidptr)", ARG5, sizeof(Int));
sewardj45f4e7c2005-09-27 19:20:21 +0000832 if (!VG_(am_is_valid_for_client)(ARG5, sizeof(Int),
833 VKI_PROT_WRITE)) {
sewardja8d8e232005-06-07 20:04:56 +0000834 SET_STATUS_Failure( VKI_EFAULT );
sewardjb5f6f512005-03-10 23:59:00 +0000835 return;
836 }
837 }
838 if (ARG1 & VKI_CLONE_SETTLS) {
839 PRE_MEM_READ("clone(tls_user_desc)", ARG4, sizeof(vki_modify_ldt_t));
sewardj45f4e7c2005-09-27 19:20:21 +0000840 if (!VG_(am_is_valid_for_client)(ARG4, sizeof(vki_modify_ldt_t),
841 VKI_PROT_READ)) {
sewardja8d8e232005-06-07 20:04:56 +0000842 SET_STATUS_Failure( VKI_EFAULT );
sewardjb5f6f512005-03-10 23:59:00 +0000843 return;
844 }
845 }
846
847 cloneflags = ARG1;
848
sewardj7eb7c582005-06-23 01:02:53 +0000849 if (!ML_(client_signal_OK)(ARG1 & VKI_CSIGNAL)) {
sewardja8d8e232005-06-07 20:04:56 +0000850 SET_STATUS_Failure( VKI_EINVAL );
sewardjb5f6f512005-03-10 23:59:00 +0000851 return;
852 }
853
sewardj468dc792005-05-31 10:12:06 +0000854 /* Be ultra-paranoid and filter out any clone-variants we don't understand:
855 - ??? specifies clone flags of 0x100011
856 - ??? specifies clone flags of 0x1200011.
857 - NPTL specifies clone flags of 0x7D0F00.
858 - The Quadrics Elan3 driver specifies clone flags of 0xF00.
sewardjde2b1602005-11-05 15:13:23 +0000859 - Newer Quadrics Elan3 drivers with NTPL support specify 0x410F00.
sewardj468dc792005-05-31 10:12:06 +0000860 Everything else is rejected.
861 */
sewardj934d2d52005-05-31 13:08:03 +0000862 if (
sewardjde2b1602005-11-05 15:13:23 +0000863 1 ||
864 /* 11 Nov 05: for the time being, disable this ultra-paranoia.
865 The switch below probably does a good enough job. */
sewardj934d2d52005-05-31 13:08:03 +0000866 (cloneflags == 0x100011 || cloneflags == 0x1200011
867 || cloneflags == 0x7D0F00
sewardja8d8e232005-06-07 20:04:56 +0000868 || cloneflags == 0x790F00
sewardjd15ce0c2005-05-31 21:07:01 +0000869 || cloneflags == 0x3D0F00
sewardjde2b1602005-11-05 15:13:23 +0000870 || cloneflags == 0x410F00
sewardj934d2d52005-05-31 13:08:03 +0000871 || cloneflags == 0xF00
872 || cloneflags == 0xF21)) {
873 /* OK */
sewardj468dc792005-05-31 10:12:06 +0000874 }
875 else {
876 /* Nah. We don't like it. Go away. */
877 goto reject;
878 }
879
sewardjb5f6f512005-03-10 23:59:00 +0000880 /* Only look at the flags we really care about */
sewardja8d8e232005-06-07 20:04:56 +0000881 switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS
882 | VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
sewardjb5f6f512005-03-10 23:59:00 +0000883 case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
884 /* thread creation */
sewardja8d8e232005-06-07 20:04:56 +0000885 SET_STATUS_from_SysRes(
886 do_clone(tid,
887 ARG1, /* flags */
888 (Addr)ARG2, /* child ESP */
889 (Int *)ARG3, /* parent_tidptr */
890 (Int *)ARG5, /* child_tidptr */
891 (vki_modify_ldt_t *)ARG4)); /* set_tls */
sewardjb5f6f512005-03-10 23:59:00 +0000892 break;
893
894 case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
895 /* FALLTHROUGH - assume vfork == fork */
896 cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
897
898 case 0: /* plain fork */
sewardja8d8e232005-06-07 20:04:56 +0000899 SET_STATUS_from_SysRes(
njne1486662005-11-10 02:48:04 +0000900 ML_(do_fork_clone)(tid,
sewardje7aa4ae2005-06-09 12:43:42 +0000901 cloneflags, /* flags */
sewardja8d8e232005-06-07 20:04:56 +0000902 (Int *)ARG3, /* parent_tidptr */
903 (Int *)ARG5)); /* child_tidptr */
sewardjb5f6f512005-03-10 23:59:00 +0000904 break;
905
906 default:
sewardj468dc792005-05-31 10:12:06 +0000907 reject:
sewardjb5f6f512005-03-10 23:59:00 +0000908 /* should we just ENOSYS? */
sewardj468dc792005-05-31 10:12:06 +0000909 VG_(message)(Vg_UserMsg, "");
910 VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%x", ARG1);
911 VG_(message)(Vg_UserMsg, "");
sewardj468dc792005-05-31 10:12:06 +0000912 VG_(message)(Vg_UserMsg, "The only supported clone() uses are:");
913 VG_(message)(Vg_UserMsg, " - via a threads library (LinuxThreads or NPTL)");
914 VG_(message)(Vg_UserMsg, " - via the implementation of fork or vfork");
915 VG_(message)(Vg_UserMsg, " - for the Quadrics Elan3 user-space driver");
sewardjb5f6f512005-03-10 23:59:00 +0000916 VG_(unimplemented)
sewardj468dc792005-05-31 10:12:06 +0000917 ("Valgrind does not support general clone().");
sewardjb5f6f512005-03-10 23:59:00 +0000918 }
919
sewardja8d8e232005-06-07 20:04:56 +0000920 if (SUCCESS) {
sewardjb5f6f512005-03-10 23:59:00 +0000921 if (ARG1 & VKI_CLONE_PARENT_SETTID)
922 POST_MEM_WRITE(ARG3, sizeof(Int));
923 if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID))
924 POST_MEM_WRITE(ARG5, sizeof(Int));
925
926 /* Thread creation was successful; let the child have the chance
927 to run */
sewardja8d8e232005-06-07 20:04:56 +0000928 *flags |= SfYieldAfter;
sewardjb5f6f512005-03-10 23:59:00 +0000929 }
930}
931
sewardja8d8e232005-06-07 20:04:56 +0000932PRE(sys_sigreturn)
sewardjb5f6f512005-03-10 23:59:00 +0000933{
sewardja8d8e232005-06-07 20:04:56 +0000934 ThreadState* tst;
sewardjb5f6f512005-03-10 23:59:00 +0000935 PRINT("sigreturn ( )");
936
sewardja8d8e232005-06-07 20:04:56 +0000937 vg_assert(VG_(is_valid_tid)(tid));
938 vg_assert(tid >= 1 && tid < VG_N_THREADS);
939 vg_assert(VG_(is_running_thread)(tid));
940
sewardjb5f6f512005-03-10 23:59:00 +0000941 /* Adjust esp to point to start of frame; skip back up over
942 sigreturn sequence's "popl %eax" and handler ret addr */
sewardja8d8e232005-06-07 20:04:56 +0000943 tst = VG_(get_ThreadState)(tid);
sewardjb5f6f512005-03-10 23:59:00 +0000944 tst->arch.vex.guest_ESP -= sizeof(Addr)+sizeof(Word);
945
946 /* This is only so that the EIP is (might be) useful to report if
947 something goes wrong in the sigreturn */
sewardj7eb7c582005-06-23 01:02:53 +0000948 ML_(fixup_guest_state_to_restart_syscall)(&tst->arch);
sewardjb5f6f512005-03-10 23:59:00 +0000949
sewardj985fabb2005-04-24 14:18:14 +0000950 VG_(sigframe_destroy)(tid, False);
sewardjb5f6f512005-03-10 23:59:00 +0000951
sewardja8d8e232005-06-07 20:04:56 +0000952 /* For unclear reasons, it appears we need the syscall to return
953 without changing %EAX. Since %EAX is the return value, and can
954 denote either success or failure, we must set up so that the
955 driver logic copies it back unchanged. Also, note %EAX is of
956 the guest registers written by VG_(sigframe_destroy). */
cerion85665ca2005-06-20 15:51:07 +0000957 SET_STATUS_from_SysRes( VG_(mk_SysRes_x86_linux)( tst->arch.vex.guest_EAX ) );
sewardjb5f6f512005-03-10 23:59:00 +0000958
sewardja8d8e232005-06-07 20:04:56 +0000959 /* Check to see if some any signals arose as a result of this. */
960 *flags |= SfPollAfter;
nethercote3d5e9102004-11-17 18:22:38 +0000961}
962
sewardja8d8e232005-06-07 20:04:56 +0000963PRE(sys_rt_sigreturn)
sewardjd571aff2005-03-15 14:47:30 +0000964{
sewardja8d8e232005-06-07 20:04:56 +0000965 ThreadState* tst;
sewardjd571aff2005-03-15 14:47:30 +0000966 PRINT("rt_sigreturn ( )");
967
sewardja8d8e232005-06-07 20:04:56 +0000968 vg_assert(VG_(is_valid_tid)(tid));
969 vg_assert(tid >= 1 && tid < VG_N_THREADS);
970 vg_assert(VG_(is_running_thread)(tid));
971
sewardjd571aff2005-03-15 14:47:30 +0000972 /* Adjust esp to point to start of frame; skip back up over handler
973 ret addr */
sewardja8d8e232005-06-07 20:04:56 +0000974 tst = VG_(get_ThreadState)(tid);
sewardjd571aff2005-03-15 14:47:30 +0000975 tst->arch.vex.guest_ESP -= sizeof(Addr);
976
977 /* This is only so that the EIP is (might be) useful to report if
978 something goes wrong in the sigreturn */
sewardj7eb7c582005-06-23 01:02:53 +0000979 ML_(fixup_guest_state_to_restart_syscall)(&tst->arch);
sewardjd571aff2005-03-15 14:47:30 +0000980
sewardj5bcde922005-05-03 22:31:22 +0000981 VG_(sigframe_destroy)(tid, True);
sewardjd571aff2005-03-15 14:47:30 +0000982
sewardja8d8e232005-06-07 20:04:56 +0000983 /* For unclear reasons, it appears we need the syscall to return
984 without changing %EAX. Since %EAX is the return value, and can
985 denote either success or failure, we must set up so that the
986 driver logic copies it back unchanged. Also, note %EAX is of
987 the guest registers written by VG_(sigframe_destroy). */
cerion85665ca2005-06-20 15:51:07 +0000988 SET_STATUS_from_SysRes( VG_(mk_SysRes_x86_linux)( tst->arch.vex.guest_EAX ) );
sewardjd571aff2005-03-15 14:47:30 +0000989
sewardja8d8e232005-06-07 20:04:56 +0000990 /* Check to see if some any signals arose as a result of this. */
991 *flags |= SfPollAfter;
sewardjd571aff2005-03-15 14:47:30 +0000992}
993
sewardja8d8e232005-06-07 20:04:56 +0000994PRE(sys_modify_ldt)
nethercote8ff888f2004-11-17 17:11:45 +0000995{
njn22cfccb2004-11-27 16:10:23 +0000996 PRINT("sys_modify_ldt ( %d, %p, %d )", ARG1,ARG2,ARG3);
nethercote8ff888f2004-11-17 17:11:45 +0000997 PRE_REG_READ3(int, "modify_ldt", int, func, void *, ptr,
998 unsigned long, bytecount);
999
njn22cfccb2004-11-27 16:10:23 +00001000 if (ARG1 == 0) {
nethercote8ff888f2004-11-17 17:11:45 +00001001 /* read the LDT into ptr */
njn22cfccb2004-11-27 16:10:23 +00001002 PRE_MEM_WRITE( "modify_ldt(ptr)", ARG2, ARG3 );
nethercote8ff888f2004-11-17 17:11:45 +00001003 }
njn22cfccb2004-11-27 16:10:23 +00001004 if (ARG1 == 1 || ARG1 == 0x11) {
nethercote8ff888f2004-11-17 17:11:45 +00001005 /* write the LDT with the entry pointed at by ptr */
njn22cfccb2004-11-27 16:10:23 +00001006 PRE_MEM_READ( "modify_ldt(ptr)", ARG2, sizeof(vki_modify_ldt_t) );
nethercote8ff888f2004-11-17 17:11:45 +00001007 }
1008 /* "do" the syscall ourselves; the kernel never sees it */
sewardja8d8e232005-06-07 20:04:56 +00001009 SET_STATUS_from_SysRes( sys_modify_ldt( tid, ARG1, (void*)ARG2, ARG3 ) );
nethercote8ff888f2004-11-17 17:11:45 +00001010
sewardja8d8e232005-06-07 20:04:56 +00001011 if (ARG1 == 0 && SUCCESS && RES > 0) {
njn22cfccb2004-11-27 16:10:23 +00001012 POST_MEM_WRITE( ARG2, RES );
nethercote8ff888f2004-11-17 17:11:45 +00001013 }
1014}
1015
sewardjbc22cf72005-06-08 00:02:49 +00001016PRE(sys_set_thread_area)
1017{
1018 PRINT("sys_set_thread_area ( %p )", ARG1);
1019 PRE_REG_READ1(int, "set_thread_area", struct user_desc *, u_info)
1020 PRE_MEM_READ( "set_thread_area(u_info)", ARG1, sizeof(vki_modify_ldt_t) );
1021
1022 /* "do" the syscall ourselves; the kernel never sees it */
1023 SET_STATUS_from_SysRes( sys_set_thread_area( tid, (void *)ARG1 ) );
1024}
1025
sewardje6d5e722005-06-10 10:27:55 +00001026PRE(sys_get_thread_area)
1027{
1028 PRINT("sys_get_thread_area ( %p )", ARG1);
1029 PRE_REG_READ1(int, "get_thread_area", struct user_desc *, u_info)
1030 PRE_MEM_WRITE( "get_thread_area(u_info)", ARG1, sizeof(vki_modify_ldt_t) );
1031
1032 /* "do" the syscall ourselves; the kernel never sees it */
1033 SET_STATUS_from_SysRes( sys_get_thread_area( tid, (void *)ARG1 ) );
1034
1035 if (SUCCESS) {
1036 POST_MEM_WRITE( ARG1, sizeof(vki_modify_ldt_t) );
1037 }
1038}
sewardj8c257322005-06-08 01:01:48 +00001039
1040// Parts of this are x86-specific, but the *PEEK* cases are generic.
1041// XXX: Why is the memory pointed to by ARG3 never checked?
1042PRE(sys_ptrace)
1043{
1044 PRINT("sys_ptrace ( %d, %d, %p, %p )", ARG1,ARG2,ARG3,ARG4);
1045 PRE_REG_READ4(int, "ptrace",
1046 long, request, long, pid, long, addr, long, data);
1047 switch (ARG1) {
1048 case VKI_PTRACE_PEEKTEXT:
1049 case VKI_PTRACE_PEEKDATA:
1050 case VKI_PTRACE_PEEKUSR:
1051 PRE_MEM_WRITE( "ptrace(peek)", ARG4,
1052 sizeof (long));
1053 break;
1054 case VKI_PTRACE_GETREGS:
1055 PRE_MEM_WRITE( "ptrace(getregs)", ARG4,
1056 sizeof (struct vki_user_regs_struct));
1057 break;
1058 case VKI_PTRACE_GETFPREGS:
1059 PRE_MEM_WRITE( "ptrace(getfpregs)", ARG4,
1060 sizeof (struct vki_user_i387_struct));
1061 break;
1062 case VKI_PTRACE_GETFPXREGS:
1063 PRE_MEM_WRITE( "ptrace(getfpxregs)", ARG4,
1064 sizeof(struct vki_user_fxsr_struct) );
1065 break;
1066 case VKI_PTRACE_SETREGS:
1067 PRE_MEM_READ( "ptrace(setregs)", ARG4,
1068 sizeof (struct vki_user_regs_struct));
1069 break;
1070 case VKI_PTRACE_SETFPREGS:
1071 PRE_MEM_READ( "ptrace(setfpregs)", ARG4,
1072 sizeof (struct vki_user_i387_struct));
1073 break;
1074 case VKI_PTRACE_SETFPXREGS:
1075 PRE_MEM_READ( "ptrace(setfpxregs)", ARG4,
1076 sizeof(struct vki_user_fxsr_struct) );
1077 break;
1078 default:
1079 break;
1080 }
1081}
1082
1083POST(sys_ptrace)
1084{
1085 switch (ARG1) {
1086 case VKI_PTRACE_PEEKTEXT:
1087 case VKI_PTRACE_PEEKDATA:
1088 case VKI_PTRACE_PEEKUSR:
1089 POST_MEM_WRITE( ARG4, sizeof (long));
1090 break;
1091 case VKI_PTRACE_GETREGS:
1092 POST_MEM_WRITE( ARG4, sizeof (struct vki_user_regs_struct));
1093 break;
1094 case VKI_PTRACE_GETFPREGS:
1095 POST_MEM_WRITE( ARG4, sizeof (struct vki_user_i387_struct));
1096 break;
1097 case VKI_PTRACE_GETFPXREGS:
1098 POST_MEM_WRITE( ARG4, sizeof(struct vki_user_fxsr_struct) );
1099 break;
1100 default:
1101 break;
1102 }
1103}
njnca0518d2004-11-26 19:34:36 +00001104
njnb249fd72004-11-29 14:24:57 +00001105static Addr deref_Addr ( ThreadId tid, Addr a, Char* s )
1106{
1107 Addr* a_p = (Addr*)a;
1108 PRE_MEM_READ( s, (Addr)a_p, sizeof(Addr) );
1109 return *a_p;
1110}
njnc6168192004-11-29 13:54:10 +00001111
sewardja8d8e232005-06-07 20:04:56 +00001112PRE(sys_ipc)
njnc6168192004-11-29 13:54:10 +00001113{
1114 PRINT("sys_ipc ( %d, %d, %d, %d, %p, %d )", ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
1115 // XXX: this is simplistic -- some args are not used in all circumstances.
1116 PRE_REG_READ6(int, "ipc",
1117 vki_uint, call, int, first, int, second, int, third,
1118 void *, ptr, long, fifth)
1119
1120 switch (ARG1 /* call */) {
1121 case VKI_SEMOP:
sewardj7eb7c582005-06-23 01:02:53 +00001122 ML_(generic_PRE_sys_semop)( tid, ARG2, ARG5, ARG3 );
sewardja8d8e232005-06-07 20:04:56 +00001123 *flags |= SfMayBlock;
njnc6168192004-11-29 13:54:10 +00001124 break;
1125 case VKI_SEMGET:
1126 break;
1127 case VKI_SEMCTL:
1128 {
sewardjb369c5e2005-03-24 17:52:02 +00001129 UWord arg = deref_Addr( tid, ARG5, "semctl(arg)" );
sewardj7eb7c582005-06-23 01:02:53 +00001130 ML_(generic_PRE_sys_semctl)( tid, ARG2, ARG3, ARG4, arg );
njnc6168192004-11-29 13:54:10 +00001131 break;
1132 }
1133 case VKI_SEMTIMEDOP:
sewardj7eb7c582005-06-23 01:02:53 +00001134 ML_(generic_PRE_sys_semtimedop)( tid, ARG2, ARG5, ARG3, ARG6 );
sewardja8d8e232005-06-07 20:04:56 +00001135 *flags |= SfMayBlock;
njnc6168192004-11-29 13:54:10 +00001136 break;
1137 case VKI_MSGSND:
njncd405ea2005-08-31 02:44:31 +00001138 ML_(linux_PRE_sys_msgsnd)( tid, ARG2, ARG5, ARG3, ARG4 );
sewardja8d8e232005-06-07 20:04:56 +00001139 if ((ARG4 & VKI_IPC_NOWAIT) == 0)
1140 *flags |= SfMayBlock;
njnc6168192004-11-29 13:54:10 +00001141 break;
njnc6168192004-11-29 13:54:10 +00001142 case VKI_MSGRCV:
1143 {
sewardjb369c5e2005-03-24 17:52:02 +00001144 Addr msgp;
1145 Word msgtyp;
njnc6168192004-11-29 13:54:10 +00001146
sewardjb369c5e2005-03-24 17:52:02 +00001147 msgp = deref_Addr( tid,
1148 (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgp),
1149 "msgrcv(msgp)" );
1150 msgtyp = deref_Addr( tid,
1151 (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgtyp),
1152 "msgrcv(msgp)" );
njnc6168192004-11-29 13:54:10 +00001153
njncd405ea2005-08-31 02:44:31 +00001154 ML_(linux_PRE_sys_msgrcv)( tid, ARG2, msgp, ARG3, msgtyp, ARG4 );
njnc6168192004-11-29 13:54:10 +00001155
sewardja8d8e232005-06-07 20:04:56 +00001156 if ((ARG4 & VKI_IPC_NOWAIT) == 0)
1157 *flags |= SfMayBlock;
njnc6168192004-11-29 13:54:10 +00001158 break;
1159 }
1160 case VKI_MSGGET:
1161 break;
1162 case VKI_MSGCTL:
njncd405ea2005-08-31 02:44:31 +00001163 ML_(linux_PRE_sys_msgctl)( tid, ARG2, ARG3, ARG5 );
njnc6168192004-11-29 13:54:10 +00001164 break;
njnc6168192004-11-29 13:54:10 +00001165 case VKI_SHMAT:
sewardja8d8e232005-06-07 20:04:56 +00001166 {
1167 UWord w;
sewardjb369c5e2005-03-24 17:52:02 +00001168 PRE_MEM_WRITE( "shmat(raddr)", ARG4, sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001169 w = ML_(generic_PRE_sys_shmat)( tid, ARG2, ARG5, ARG3 );
sewardja8d8e232005-06-07 20:04:56 +00001170 if (w == 0)
1171 SET_STATUS_Failure( VKI_EINVAL );
1172 else
1173 ARG5 = w;
njnc6168192004-11-29 13:54:10 +00001174 break;
sewardja8d8e232005-06-07 20:04:56 +00001175 }
njnc6168192004-11-29 13:54:10 +00001176 case VKI_SHMDT:
sewardj7eb7c582005-06-23 01:02:53 +00001177 if (!ML_(generic_PRE_sys_shmdt)(tid, ARG5))
sewardja8d8e232005-06-07 20:04:56 +00001178 SET_STATUS_Failure( VKI_EINVAL );
njnc6168192004-11-29 13:54:10 +00001179 break;
1180 case VKI_SHMGET:
1181 break;
1182 case VKI_SHMCTL: /* IPCOP_shmctl */
sewardj7eb7c582005-06-23 01:02:53 +00001183 ML_(generic_PRE_sys_shmctl)( tid, ARG2, ARG3, ARG5 );
njnc6168192004-11-29 13:54:10 +00001184 break;
njnc6168192004-11-29 13:54:10 +00001185 default:
1186 VG_(message)(Vg_DebugMsg, "FATAL: unhandled syscall(ipc) %d", ARG1 );
1187 VG_(core_panic)("... bye!\n");
1188 break; /*NOTREACHED*/
1189 }
1190}
1191
1192POST(sys_ipc)
1193{
sewardja8d8e232005-06-07 20:04:56 +00001194 vg_assert(SUCCESS);
njnc6168192004-11-29 13:54:10 +00001195 switch (ARG1 /* call */) {
1196 case VKI_SEMOP:
1197 case VKI_SEMGET:
1198 break;
1199 case VKI_SEMCTL:
1200 {
sewardjb369c5e2005-03-24 17:52:02 +00001201 UWord arg = deref_Addr( tid, ARG5, "semctl(arg)" );
sewardj7eb7c582005-06-23 01:02:53 +00001202 ML_(generic_PRE_sys_semctl)( tid, ARG2, ARG3, ARG4, arg );
njnc6168192004-11-29 13:54:10 +00001203 break;
1204 }
1205 case VKI_SEMTIMEDOP:
1206 case VKI_MSGSND:
1207 break;
1208 case VKI_MSGRCV:
1209 {
sewardjb369c5e2005-03-24 17:52:02 +00001210 Addr msgp;
1211 Word msgtyp;
1212
1213 msgp = deref_Addr( tid,
1214 (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgp),
1215 "msgrcv(msgp)" );
1216 msgtyp = deref_Addr( tid,
1217 (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgtyp),
1218 "msgrcv(msgp)" );
1219
njncd405ea2005-08-31 02:44:31 +00001220 ML_(linux_POST_sys_msgrcv)( tid, RES, ARG2, msgp, ARG3, msgtyp, ARG4 );
njnc6168192004-11-29 13:54:10 +00001221 break;
1222 }
1223 case VKI_MSGGET:
1224 break;
1225 case VKI_MSGCTL:
njncd405ea2005-08-31 02:44:31 +00001226 ML_(linux_POST_sys_msgctl)( tid, RES, ARG2, ARG3, ARG5 );
njnc6168192004-11-29 13:54:10 +00001227 break;
njnc6168192004-11-29 13:54:10 +00001228 case VKI_SHMAT:
1229 {
njnc6168192004-11-29 13:54:10 +00001230 Addr addr;
1231
1232 /* force readability. before the syscall it is
1233 * indeed uninitialized, as can be seen in
1234 * glibc/sysdeps/unix/sysv/linux/shmat.c */
sewardjb369c5e2005-03-24 17:52:02 +00001235 POST_MEM_WRITE( ARG4, sizeof( Addr ) );
njnc6168192004-11-29 13:54:10 +00001236
1237 addr = deref_Addr ( tid, ARG4, "shmat(addr)" );
1238 if ( addr > 0 ) {
sewardj7eb7c582005-06-23 01:02:53 +00001239 ML_(generic_POST_sys_shmat)( tid, addr, ARG2, ARG5, ARG3 );
njnc6168192004-11-29 13:54:10 +00001240 }
1241 break;
1242 }
1243 case VKI_SHMDT:
sewardj7eb7c582005-06-23 01:02:53 +00001244 ML_(generic_POST_sys_shmdt)( tid, RES, ARG5 );
njnc6168192004-11-29 13:54:10 +00001245 break;
njnc6168192004-11-29 13:54:10 +00001246 case VKI_SHMGET:
1247 break;
1248 case VKI_SHMCTL:
sewardj7eb7c582005-06-23 01:02:53 +00001249 ML_(generic_POST_sys_shmctl)( tid, RES, ARG2, ARG3, ARG5 );
njnc6168192004-11-29 13:54:10 +00001250 break;
njnc6168192004-11-29 13:54:10 +00001251 default:
1252 VG_(message)(Vg_DebugMsg,
1253 "FATAL: unhandled syscall(ipc) %d",
1254 ARG1 );
1255 VG_(core_panic)("... bye!\n");
1256 break; /*NOTREACHED*/
1257 }
1258}
1259
sewardja8d8e232005-06-07 20:04:56 +00001260PRE(old_mmap)
sewardjb5f6f512005-03-10 23:59:00 +00001261{
sewardja8d8e232005-06-07 20:04:56 +00001262 /* struct mmap_arg_struct {
1263 unsigned long addr;
1264 unsigned long len;
1265 unsigned long prot;
1266 unsigned long flags;
1267 unsigned long fd;
1268 unsigned long offset;
1269 }; */
1270 UWord a1, a2, a3, a4, a5, a6;
tom9548a162005-09-30 08:07:53 +00001271 SysRes r;
sewardja8d8e232005-06-07 20:04:56 +00001272
sewardje6d5e722005-06-10 10:27:55 +00001273 UWord* args = (UWord*)ARG1;
1274 PRE_REG_READ1(long, "old_mmap", struct mmap_arg_struct *, args);
1275 PRE_MEM_READ( "old_mmap(args)", (Addr)args, 6*sizeof(UWord) );
sewardja8d8e232005-06-07 20:04:56 +00001276
sewardj45f4e7c2005-09-27 19:20:21 +00001277 a1 = args[1-1];
1278 a2 = args[2-1];
1279 a3 = args[3-1];
1280 a4 = args[4-1];
1281 a5 = args[5-1];
1282 a6 = args[6-1];
sewardja8d8e232005-06-07 20:04:56 +00001283
1284 PRINT("old_mmap ( %p, %llu, %d, %d, %d, %d )",
1285 a1, (ULong)a2, a3, a4, a5, a6 );
1286
sewardj274461d2005-10-02 17:01:41 +00001287 r = ML_(generic_PRE_sys_mmap)( tid, a1, a2, a3, a4, a5, (Off64T)a6 );
tom9548a162005-09-30 08:07:53 +00001288 SET_STATUS_from_SysRes(r);
1289}
sewardja8d8e232005-06-07 20:04:56 +00001290
tom9548a162005-09-30 08:07:53 +00001291PRE(sys_mmap2)
1292{
1293 SysRes r;
sewardja8d8e232005-06-07 20:04:56 +00001294
tom9548a162005-09-30 08:07:53 +00001295 // Exactly like old_mmap() except:
1296 // - all 6 args are passed in regs, rather than in a memory-block.
1297 // - the file offset is specified in pagesize units rather than bytes,
1298 // so that it can be used for files bigger than 2^32 bytes.
1299 PRINT("sys_mmap2 ( %p, %llu, %d, %d, %d, %d )",
1300 ARG1, (ULong)ARG2, ARG3, ARG4, ARG5, ARG6 );
1301 PRE_REG_READ6(long, "mmap2",
1302 unsigned long, start, unsigned long, length,
1303 unsigned long, prot, unsigned long, flags,
1304 unsigned long, fd, unsigned long, offset);
sewardja8d8e232005-06-07 20:04:56 +00001305
sewardj274461d2005-10-02 17:01:41 +00001306 r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5,
1307 VKI_PAGE_SIZE * (Off64T)ARG6 );
tom9548a162005-09-30 08:07:53 +00001308 SET_STATUS_from_SysRes(r);
sewardjb5f6f512005-03-10 23:59:00 +00001309}
sewardja8d8e232005-06-07 20:04:56 +00001310
1311// XXX: lstat64/fstat64/stat64 are generic, but not necessarily
1312// applicable to every architecture -- I think only to 32-bit archs.
1313// We're going to need something like linux/core_os32.h for such
1314// things, eventually, I think. --njn
1315PRE(sys_lstat64)
njnc6168192004-11-29 13:54:10 +00001316{
sewardja8d8e232005-06-07 20:04:56 +00001317 PRINT("sys_lstat64 ( %p(%s), %p )",ARG1,ARG1,ARG2);
1318 PRE_REG_READ2(long, "lstat64", char *, file_name, struct stat64 *, buf);
1319 PRE_MEM_RASCIIZ( "lstat64(file_name)", ARG1 );
1320 PRE_MEM_WRITE( "lstat64(buf)", ARG2, sizeof(struct vki_stat64) );
1321}
sewardjb5f6f512005-03-10 23:59:00 +00001322
sewardja8d8e232005-06-07 20:04:56 +00001323POST(sys_lstat64)
1324{
1325 vg_assert(SUCCESS);
1326 if (RES == 0) {
1327 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
sewardjb5f6f512005-03-10 23:59:00 +00001328 }
njnc6168192004-11-29 13:54:10 +00001329}
1330
sewardja8d8e232005-06-07 20:04:56 +00001331PRE(sys_stat64)
njnc6168192004-11-29 13:54:10 +00001332{
sewardja8d8e232005-06-07 20:04:56 +00001333 PRINT("sys_stat64 ( %p, %p )",ARG1,ARG2);
1334 PRE_REG_READ2(long, "stat64", char *, file_name, struct stat64 *, buf);
1335 PRE_MEM_RASCIIZ( "stat64(file_name)", ARG1 );
1336 PRE_MEM_WRITE( "stat64(buf)", ARG2, sizeof(struct vki_stat64) );
njnc6168192004-11-29 13:54:10 +00001337}
1338
sewardja8d8e232005-06-07 20:04:56 +00001339POST(sys_stat64)
1340{
1341 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
1342}
1343
1344PRE(sys_fstat64)
1345{
1346 PRINT("sys_fstat64 ( %d, %p )",ARG1,ARG2);
1347 PRE_REG_READ2(long, "fstat64", unsigned long, fd, struct stat64 *, buf);
1348 PRE_MEM_WRITE( "fstat64(buf)", ARG2, sizeof(struct vki_stat64) );
1349}
1350
1351POST(sys_fstat64)
1352{
1353 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
1354}
1355
1356PRE(sys_socketcall)
1357{
1358# define ARG2_0 (((UWord*)ARG2)[0])
1359# define ARG2_1 (((UWord*)ARG2)[1])
1360# define ARG2_2 (((UWord*)ARG2)[2])
1361# define ARG2_3 (((UWord*)ARG2)[3])
1362# define ARG2_4 (((UWord*)ARG2)[4])
1363# define ARG2_5 (((UWord*)ARG2)[5])
1364
1365 *flags |= SfMayBlock;
1366 PRINT("sys_socketcall ( %d, %p )",ARG1,ARG2);
1367 PRE_REG_READ2(long, "socketcall", int, call, unsigned long *, args);
1368
1369 switch (ARG1 /* request */) {
1370
1371 case VKI_SYS_SOCKETPAIR:
1372 /* int socketpair(int d, int type, int protocol, int sv[2]); */
1373 PRE_MEM_READ( "socketcall.socketpair(args)", ARG2, 4*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001374 ML_(generic_PRE_sys_socketpair)( tid, ARG2_0, ARG2_1, ARG2_2, ARG2_3 );
sewardja8d8e232005-06-07 20:04:56 +00001375 break;
1376
1377 case VKI_SYS_SOCKET:
1378 /* int socket(int domain, int type, int protocol); */
1379 PRE_MEM_READ( "socketcall.socket(args)", ARG2, 3*sizeof(Addr) );
1380 break;
1381
1382 case VKI_SYS_BIND:
1383 /* int bind(int sockfd, struct sockaddr *my_addr,
1384 int addrlen); */
1385 PRE_MEM_READ( "socketcall.bind(args)", ARG2, 3*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001386 ML_(generic_PRE_sys_bind)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001387 break;
1388
1389 case VKI_SYS_LISTEN:
1390 /* int listen(int s, int backlog); */
1391 PRE_MEM_READ( "socketcall.listen(args)", ARG2, 2*sizeof(Addr) );
1392 break;
1393
1394 case VKI_SYS_ACCEPT: {
1395 /* int accept(int s, struct sockaddr *addr, int *addrlen); */
1396 PRE_MEM_READ( "socketcall.accept(args)", ARG2, 3*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001397 ML_(generic_PRE_sys_accept)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001398 break;
1399 }
1400
1401 case VKI_SYS_SENDTO:
1402 /* int sendto(int s, const void *msg, int len,
1403 unsigned int flags,
1404 const struct sockaddr *to, int tolen); */
1405 PRE_MEM_READ( "socketcall.sendto(args)", ARG2, 6*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001406 ML_(generic_PRE_sys_sendto)( tid, ARG2_0, ARG2_1, ARG2_2,
sewardja8d8e232005-06-07 20:04:56 +00001407 ARG2_3, ARG2_4, ARG2_5 );
1408 break;
1409
1410 case VKI_SYS_SEND:
1411 /* int send(int s, const void *msg, size_t len, int flags); */
1412 PRE_MEM_READ( "socketcall.send(args)", ARG2, 4*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001413 ML_(generic_PRE_sys_send)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001414 break;
1415
1416 case VKI_SYS_RECVFROM:
1417 /* int recvfrom(int s, void *buf, int len, unsigned int flags,
1418 struct sockaddr *from, int *fromlen); */
1419 PRE_MEM_READ( "socketcall.recvfrom(args)", ARG2, 6*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001420 ML_(generic_PRE_sys_recvfrom)( tid, ARG2_0, ARG2_1, ARG2_2,
sewardja8d8e232005-06-07 20:04:56 +00001421 ARG2_3, ARG2_4, ARG2_5 );
1422 break;
1423
1424 case VKI_SYS_RECV:
1425 /* int recv(int s, void *buf, int len, unsigned int flags); */
1426 /* man 2 recv says:
1427 The recv call is normally used only on a connected socket
1428 (see connect(2)) and is identical to recvfrom with a NULL
1429 from parameter.
1430 */
1431 PRE_MEM_READ( "socketcall.recv(args)", ARG2, 4*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001432 ML_(generic_PRE_sys_recv)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001433 break;
1434
1435 case VKI_SYS_CONNECT:
1436 /* int connect(int sockfd,
1437 struct sockaddr *serv_addr, int addrlen ); */
1438 PRE_MEM_READ( "socketcall.connect(args)", ARG2, 3*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001439 ML_(generic_PRE_sys_connect)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001440 break;
1441
1442 case VKI_SYS_SETSOCKOPT:
1443 /* int setsockopt(int s, int level, int optname,
1444 const void *optval, int optlen); */
1445 PRE_MEM_READ( "socketcall.setsockopt(args)", ARG2, 5*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001446 ML_(generic_PRE_sys_setsockopt)( tid, ARG2_0, ARG2_1, ARG2_2,
sewardja8d8e232005-06-07 20:04:56 +00001447 ARG2_3, ARG2_4 );
1448 break;
1449
1450 case VKI_SYS_GETSOCKOPT:
1451 /* int getsockopt(int s, int level, int optname,
1452 void *optval, socklen_t *optlen); */
1453 PRE_MEM_READ( "socketcall.getsockopt(args)", ARG2, 5*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001454 ML_(generic_PRE_sys_getsockopt)( tid, ARG2_0, ARG2_1, ARG2_2,
sewardja8d8e232005-06-07 20:04:56 +00001455 ARG2_3, ARG2_4 );
1456 break;
1457
1458 case VKI_SYS_GETSOCKNAME:
1459 /* int getsockname(int s, struct sockaddr* name, int* namelen) */
1460 PRE_MEM_READ( "socketcall.getsockname(args)", ARG2, 3*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001461 ML_(generic_PRE_sys_getsockname)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001462 break;
1463
1464 case VKI_SYS_GETPEERNAME:
1465 /* int getpeername(int s, struct sockaddr* name, int* namelen) */
1466 PRE_MEM_READ( "socketcall.getpeername(args)", ARG2, 3*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001467 ML_(generic_PRE_sys_getpeername)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001468 break;
1469
1470 case VKI_SYS_SHUTDOWN:
1471 /* int shutdown(int s, int how); */
1472 PRE_MEM_READ( "socketcall.shutdown(args)", ARG2, 2*sizeof(Addr) );
1473 break;
1474
1475 case VKI_SYS_SENDMSG: {
1476 /* int sendmsg(int s, const struct msghdr *msg, int flags); */
1477
1478 /* this causes warnings, and I don't get why. glibc bug?
1479 * (after all it's glibc providing the arguments array)
1480 PRE_MEM_READ( "socketcall.sendmsg(args)", ARG2, 3*sizeof(Addr) );
1481 */
sewardj7eb7c582005-06-23 01:02:53 +00001482 ML_(generic_PRE_sys_sendmsg)( tid, ARG2_0, ARG2_1 );
sewardja8d8e232005-06-07 20:04:56 +00001483 break;
1484 }
1485
1486 case VKI_SYS_RECVMSG: {
1487 /* int recvmsg(int s, struct msghdr *msg, int flags); */
1488
1489 /* this causes warnings, and I don't get why. glibc bug?
1490 * (after all it's glibc providing the arguments array)
1491 PRE_MEM_READ("socketcall.recvmsg(args)", ARG2, 3*sizeof(Addr) );
1492 */
sewardj7eb7c582005-06-23 01:02:53 +00001493 ML_(generic_PRE_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
sewardja8d8e232005-06-07 20:04:56 +00001494 break;
1495 }
1496
1497 default:
1498 VG_(message)(Vg_DebugMsg,"Warning: unhandled socketcall 0x%x",ARG1);
1499 SET_STATUS_Failure( VKI_EINVAL );
1500 break;
1501 }
1502# undef ARG2_0
1503# undef ARG2_1
1504# undef ARG2_2
1505# undef ARG2_3
1506# undef ARG2_4
1507# undef ARG2_5
1508}
1509
1510POST(sys_socketcall)
1511{
1512# define ARG2_0 (((UWord*)ARG2)[0])
1513# define ARG2_1 (((UWord*)ARG2)[1])
1514# define ARG2_2 (((UWord*)ARG2)[2])
1515# define ARG2_3 (((UWord*)ARG2)[3])
1516# define ARG2_4 (((UWord*)ARG2)[4])
1517# define ARG2_5 (((UWord*)ARG2)[5])
1518
1519 SysRes r;
1520 vg_assert(SUCCESS);
1521 switch (ARG1 /* request */) {
1522
1523 case VKI_SYS_SOCKETPAIR:
sewardj7eb7c582005-06-23 01:02:53 +00001524 r = ML_(generic_POST_sys_socketpair)(
sewardja8d8e232005-06-07 20:04:56 +00001525 tid, VG_(mk_SysRes_Success)(RES),
1526 ARG2_0, ARG2_1, ARG2_2, ARG2_3
1527 );
1528 SET_STATUS_from_SysRes(r);
1529 break;
1530
1531 case VKI_SYS_SOCKET:
sewardj7eb7c582005-06-23 01:02:53 +00001532 r = ML_(generic_POST_sys_socket)( tid, VG_(mk_SysRes_Success)(RES) );
sewardja8d8e232005-06-07 20:04:56 +00001533 SET_STATUS_from_SysRes(r);
1534 break;
1535
1536 case VKI_SYS_BIND:
1537 /* int bind(int sockfd, struct sockaddr *my_addr,
1538 int addrlen); */
1539 break;
1540
1541 case VKI_SYS_LISTEN:
1542 /* int listen(int s, int backlog); */
1543 break;
1544
1545 case VKI_SYS_ACCEPT:
1546 /* int accept(int s, struct sockaddr *addr, int *addrlen); */
sewardj7eb7c582005-06-23 01:02:53 +00001547 r = ML_(generic_POST_sys_accept)( tid, VG_(mk_SysRes_Success)(RES),
sewardja8d8e232005-06-07 20:04:56 +00001548 ARG2_0, ARG2_1, ARG2_2 );
1549 SET_STATUS_from_SysRes(r);
1550 break;
1551
1552 case VKI_SYS_SENDTO:
1553 break;
1554
1555 case VKI_SYS_SEND:
1556 break;
1557
1558 case VKI_SYS_RECVFROM:
sewardj7eb7c582005-06-23 01:02:53 +00001559 ML_(generic_POST_sys_recvfrom)( tid, VG_(mk_SysRes_Success)(RES),
sewardja8d8e232005-06-07 20:04:56 +00001560 ARG2_0, ARG2_1, ARG2_2,
1561 ARG2_3, ARG2_4, ARG2_5 );
1562 break;
1563
1564 case VKI_SYS_RECV:
sewardj7eb7c582005-06-23 01:02:53 +00001565 ML_(generic_POST_sys_recv)( tid, RES, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001566 break;
1567
1568 case VKI_SYS_CONNECT:
1569 break;
1570
1571 case VKI_SYS_SETSOCKOPT:
1572 break;
1573
1574 case VKI_SYS_GETSOCKOPT:
sewardj7eb7c582005-06-23 01:02:53 +00001575 ML_(generic_POST_sys_getsockopt)( tid, VG_(mk_SysRes_Success)(RES),
sewardja8d8e232005-06-07 20:04:56 +00001576 ARG2_0, ARG2_1,
1577 ARG2_2, ARG2_3, ARG2_4 );
1578 break;
1579
1580 case VKI_SYS_GETSOCKNAME:
sewardj7eb7c582005-06-23 01:02:53 +00001581 ML_(generic_POST_sys_getsockname)( tid, VG_(mk_SysRes_Success)(RES),
sewardja8d8e232005-06-07 20:04:56 +00001582 ARG2_0, ARG2_1, ARG2_2 );
1583 break;
1584
1585 case VKI_SYS_GETPEERNAME:
sewardj7eb7c582005-06-23 01:02:53 +00001586 ML_(generic_POST_sys_getpeername)( tid, VG_(mk_SysRes_Success)(RES),
sewardja8d8e232005-06-07 20:04:56 +00001587 ARG2_0, ARG2_1, ARG2_2 );
1588 break;
1589
1590 case VKI_SYS_SHUTDOWN:
1591 break;
1592
1593 case VKI_SYS_SENDMSG:
1594 break;
1595
1596 case VKI_SYS_RECVMSG:
sewardj7eb7c582005-06-23 01:02:53 +00001597 ML_(generic_POST_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
sewardja8d8e232005-06-07 20:04:56 +00001598 break;
1599
1600 default:
1601 VG_(message)(Vg_DebugMsg,"FATAL: unhandled socketcall 0x%x",ARG1);
1602 VG_(core_panic)("... bye!\n");
1603 break; /*NOTREACHED*/
1604 }
1605# undef ARG2_0
1606# undef ARG2_1
1607# undef ARG2_2
1608# undef ARG2_3
1609# undef ARG2_4
1610# undef ARG2_5
1611}
1612
sewardj696c5512005-06-08 23:38:32 +00001613/* Convert from non-RT to RT sigset_t's */
1614static
1615void convert_sigset_to_rt(const vki_old_sigset_t *oldset, vki_sigset_t *set)
1616{
1617 VG_(sigemptyset)(set);
1618 set->sig[0] = *oldset;
1619}
1620PRE(sys_sigaction)
1621{
1622 struct vki_sigaction new, old;
1623 struct vki_sigaction *newp, *oldp;
1624
1625 PRINT("sys_sigaction ( %d, %p, %p )", ARG1,ARG2,ARG3);
1626 PRE_REG_READ3(int, "sigaction",
1627 int, signum, const struct old_sigaction *, act,
1628 struct old_sigaction *, oldact);
1629
1630 newp = oldp = NULL;
1631
tomd9cac2f2005-08-07 15:16:59 +00001632 if (ARG2 != 0) {
1633 struct vki_old_sigaction *sa = (struct vki_old_sigaction *)ARG2;
tom9b52a342005-08-08 16:50:16 +00001634 PRE_MEM_READ( "sigaction(act->sa_handler)", (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler));
1635 PRE_MEM_READ( "sigaction(act->sa_mask)", (Addr)&sa->sa_mask, sizeof(sa->sa_mask));
1636 PRE_MEM_READ( "sigaction(act->sa_flags)", (Addr)&sa->sa_flags, sizeof(sa->sa_flags));
sewardj45f4e7c2005-09-27 19:20:21 +00001637 if (ML_(safe_to_deref)(sa,sizeof(sa))
1638 && (sa->sa_flags & VKI_SA_RESTORER))
tom9b52a342005-08-08 16:50:16 +00001639 PRE_MEM_READ( "sigaction(act->sa_restorer)", (Addr)&sa->sa_restorer, sizeof(sa->sa_restorer));
tomd9cac2f2005-08-07 15:16:59 +00001640 }
sewardj696c5512005-06-08 23:38:32 +00001641
1642 if (ARG3 != 0) {
1643 PRE_MEM_WRITE( "sigaction(oldact)", ARG3, sizeof(struct vki_old_sigaction));
1644 oldp = &old;
1645 }
1646
1647 //jrs 20050207: what?! how can this make any sense?
1648 //if (VG_(is_kerror)(SYSRES))
1649 // return;
1650
1651 if (ARG2 != 0) {
1652 struct vki_old_sigaction *oldnew = (struct vki_old_sigaction *)ARG2;
1653
1654 new.ksa_handler = oldnew->ksa_handler;
1655 new.sa_flags = oldnew->sa_flags;
1656 new.sa_restorer = oldnew->sa_restorer;
1657 convert_sigset_to_rt(&oldnew->sa_mask, &new.sa_mask);
1658 newp = &new;
1659 }
1660
1661 SET_STATUS_from_SysRes( VG_(do_sys_sigaction)(ARG1, newp, oldp) );
1662
1663 if (ARG3 != 0 && SUCCESS && RES == 0) {
1664 struct vki_old_sigaction *oldold = (struct vki_old_sigaction *)ARG3;
1665
1666 oldold->ksa_handler = oldp->ksa_handler;
1667 oldold->sa_flags = oldp->sa_flags;
1668 oldold->sa_restorer = oldp->sa_restorer;
1669 oldold->sa_mask = oldp->sa_mask.sig[0];
1670 }
1671}
1672
1673POST(sys_sigaction)
1674{
1675 vg_assert(SUCCESS);
1676 if (RES == 0 && ARG3 != 0)
1677 POST_MEM_WRITE( ARG3, sizeof(struct vki_old_sigaction));
1678}
1679
sewardjce5a5662005-10-06 03:19:49 +00001680
1681/* ---------------------------------------------------------------
1682 PRE/POST wrappers for x86/Linux-variant specific syscalls
1683 ------------------------------------------------------------ */
1684
1685PRE(sys_syscall223)
1686{
1687 Int err;
1688
1689 /* 223 is used by sys_bproc. If we're not on a declared bproc
1690 variant, fail in the usual way. */
1691
1692 if (!VG_(strstr)(VG_(clo_kernel_variant), "bproc")) {
1693 PRINT("non-existent syscall! (syscall 223)");
1694 PRE_REG_READ0(long, "ni_syscall(223)");
1695 SET_STATUS_Failure( VKI_ENOSYS );
1696 return;
1697 }
1698
1699 err = ML_(linux_variant_PRE_sys_bproc)( ARG1, ARG2, ARG3,
1700 ARG4, ARG5, ARG6 );
1701 if (err) {
1702 SET_STATUS_Failure( err );
1703 return;
1704 }
1705 /* Let it go through. */
1706 *flags |= SfMayBlock; /* who knows? play safe. */
1707}
1708
1709POST(sys_syscall223)
1710{
1711 ML_(linux_variant_POST_sys_bproc)( ARG1, ARG2, ARG3,
1712 ARG4, ARG5, ARG6 );
1713}
1714
sewardj696c5512005-06-08 23:38:32 +00001715#undef PRE
1716#undef POST
1717
nethercote8ff888f2004-11-17 17:11:45 +00001718
1719/* ---------------------------------------------------------------------
1720 The x86/Linux syscall table
1721 ------------------------------------------------------------------ */
1722
sewardje7aa4ae2005-06-09 12:43:42 +00001723/* Add an x86-linux specific wrapper to a syscall table. */
sewardja8d8e232005-06-07 20:04:56 +00001724#define PLAX_(sysno, name) WRAPPER_ENTRY_X_(x86_linux, sysno, name)
1725#define PLAXY(sysno, name) WRAPPER_ENTRY_XY(x86_linux, sysno, name)
1726
nethercote8ff888f2004-11-17 17:11:45 +00001727
nethercote3d5e9102004-11-17 18:22:38 +00001728// This table maps from __NR_xxx syscall numbers (from
1729// linux/include/asm-i386/unistd.h) to the appropriate PRE/POST sys_foo()
1730// wrappers on x86 (as per sys_call_table in linux/arch/i386/kernel/entry.S).
1731//
1732// For those syscalls not handled by Valgrind, the annotation indicate its
1733// arch/OS combination, eg. */* (generic), */Linux (Linux only), ?/?
1734// (unknown).
1735
njnaf839f52005-06-23 03:27:57 +00001736const SyscallTableEntry ML_(syscall_table)[] = {
sewardja8d8e232005-06-07 20:04:56 +00001737//zz // (restart_syscall) // 0
nethercote8ff888f2004-11-17 17:11:45 +00001738 GENX_(__NR_exit, sys_exit), // 1
sewardjb5f6f512005-03-10 23:59:00 +00001739 GENX_(__NR_fork, sys_fork), // 2
nethercote8ff888f2004-11-17 17:11:45 +00001740 GENXY(__NR_read, sys_read), // 3
1741 GENX_(__NR_write, sys_write), // 4
1742
1743 GENXY(__NR_open, sys_open), // 5
1744 GENXY(__NR_close, sys_close), // 6
1745 GENXY(__NR_waitpid, sys_waitpid), // 7
1746 GENXY(__NR_creat, sys_creat), // 8
1747 GENX_(__NR_link, sys_link), // 9
1748
1749 GENX_(__NR_unlink, sys_unlink), // 10
nethercote3d5e9102004-11-17 18:22:38 +00001750 GENX_(__NR_execve, sys_execve), // 11
nethercote8ff888f2004-11-17 17:11:45 +00001751 GENX_(__NR_chdir, sys_chdir), // 12
1752 GENXY(__NR_time, sys_time), // 13
1753 GENX_(__NR_mknod, sys_mknod), // 14
1754
1755 GENX_(__NR_chmod, sys_chmod), // 15
njnefc957c2005-08-26 04:36:10 +00001756//zz LINX_(__NR_lchown, sys_lchown16), // 16
nethercote3d5e9102004-11-17 18:22:38 +00001757 GENX_(__NR_break, sys_ni_syscall), // 17
sewardja8d8e232005-06-07 20:04:56 +00001758//zz // (__NR_oldstat, sys_stat), // 18 (obsolete)
njncd405ea2005-08-31 02:44:31 +00001759 LINX_(__NR_lseek, sys_lseek), // 19
nethercote8ff888f2004-11-17 17:11:45 +00001760
1761 GENX_(__NR_getpid, sys_getpid), // 20
1762 LINX_(__NR_mount, sys_mount), // 21
1763 LINX_(__NR_umount, sys_oldumount), // 22
njna3b67b72005-08-26 04:27:54 +00001764 LINX_(__NR_setuid, sys_setuid16), // 23 ## P
1765 LINX_(__NR_getuid, sys_getuid16), // 24 ## P
sewardja8d8e232005-06-07 20:04:56 +00001766//zz
1767//zz // (__NR_stime, sys_stime), // 25 * (SVr4,SVID,X/OPEN)
sewardj8c257322005-06-08 01:01:48 +00001768 PLAXY(__NR_ptrace, sys_ptrace), // 26
nethercote3d5e9102004-11-17 18:22:38 +00001769 GENX_(__NR_alarm, sys_alarm), // 27
sewardja8d8e232005-06-07 20:04:56 +00001770//zz // (__NR_oldfstat, sys_fstat), // 28 * L -- obsolete
nethercote3d5e9102004-11-17 18:22:38 +00001771 GENX_(__NR_pause, sys_pause), // 29
sewardj8c9ea4e2005-06-08 10:46:56 +00001772
njncd405ea2005-08-31 02:44:31 +00001773 LINX_(__NR_utime, sys_utime), // 30
nethercote3d5e9102004-11-17 18:22:38 +00001774 GENX_(__NR_stty, sys_ni_syscall), // 31
1775 GENX_(__NR_gtty, sys_ni_syscall), // 32
1776 GENX_(__NR_access, sys_access), // 33
sewardj8c9ea4e2005-06-08 10:46:56 +00001777 GENX_(__NR_nice, sys_nice), // 34
1778
nethercote3d5e9102004-11-17 18:22:38 +00001779 GENX_(__NR_ftime, sys_ni_syscall), // 35
sewardj8c9ea4e2005-06-08 10:46:56 +00001780 GENX_(__NR_sync, sys_sync), // 36
njn03f1e582005-03-26 20:08:06 +00001781 GENX_(__NR_kill, sys_kill), // 37
nethercote8ff888f2004-11-17 17:11:45 +00001782 GENX_(__NR_rename, sys_rename), // 38
1783 GENX_(__NR_mkdir, sys_mkdir), // 39
sewardj78b50e42005-06-08 01:47:28 +00001784
1785 GENX_(__NR_rmdir, sys_rmdir), // 40
nethercote8ff888f2004-11-17 17:11:45 +00001786 GENXY(__NR_dup, sys_dup), // 41
njncd405ea2005-08-31 02:44:31 +00001787 LINXY(__NR_pipe, sys_pipe), // 42
sewardj78b50e42005-06-08 01:47:28 +00001788 GENXY(__NR_times, sys_times), // 43
nethercote3d5e9102004-11-17 18:22:38 +00001789 GENX_(__NR_prof, sys_ni_syscall), // 44
sewardja8d8e232005-06-07 20:04:56 +00001790//zz
nethercote3d5e9102004-11-17 18:22:38 +00001791 GENX_(__NR_brk, sys_brk), // 45
njna3b67b72005-08-26 04:27:54 +00001792 LINX_(__NR_setgid, sys_setgid16), // 46
1793 LINX_(__NR_getgid, sys_getgid16), // 47
sewardja8d8e232005-06-07 20:04:56 +00001794//zz // (__NR_signal, sys_signal), // 48 */* (ANSI C)
njna3b67b72005-08-26 04:27:54 +00001795 LINX_(__NR_geteuid, sys_geteuid16), // 49
sewardj696c5512005-06-08 23:38:32 +00001796
njna3b67b72005-08-26 04:27:54 +00001797 LINX_(__NR_getegid, sys_getegid16), // 50
sewardj696c5512005-06-08 23:38:32 +00001798 GENX_(__NR_acct, sys_acct), // 51
1799 LINX_(__NR_umount2, sys_umount), // 52
nethercote3d5e9102004-11-17 18:22:38 +00001800 GENX_(__NR_lock, sys_ni_syscall), // 53
1801 GENXY(__NR_ioctl, sys_ioctl), // 54
sewardj696c5512005-06-08 23:38:32 +00001802
1803 GENXY(__NR_fcntl, sys_fcntl), // 55
nethercote3d5e9102004-11-17 18:22:38 +00001804 GENX_(__NR_mpx, sys_ni_syscall), // 56
sewardj696c5512005-06-08 23:38:32 +00001805 GENX_(__NR_setpgid, sys_setpgid), // 57
nethercote3d5e9102004-11-17 18:22:38 +00001806 GENX_(__NR_ulimit, sys_ni_syscall), // 58
sewardja8d8e232005-06-07 20:04:56 +00001807//zz // (__NR_oldolduname, sys_olduname), // 59 Linux -- obsolete
1808//zz
sewardj78b50e42005-06-08 01:47:28 +00001809 GENX_(__NR_umask, sys_umask), // 60
sewardj696c5512005-06-08 23:38:32 +00001810 GENX_(__NR_chroot, sys_chroot), // 61
sewardja8d8e232005-06-07 20:04:56 +00001811//zz // (__NR_ustat, sys_ustat) // 62 SVr4 -- deprecated
nethercote8ff888f2004-11-17 17:11:45 +00001812 GENXY(__NR_dup2, sys_dup2), // 63
sewardj1d887112005-05-30 21:44:08 +00001813 GENX_(__NR_getppid, sys_getppid), // 64
sewardj78b50e42005-06-08 01:47:28 +00001814
1815 GENX_(__NR_getpgrp, sys_getpgrp), // 65
sewardj696c5512005-06-08 23:38:32 +00001816 GENX_(__NR_setsid, sys_setsid), // 66
1817 PLAXY(__NR_sigaction, sys_sigaction), // 67
sewardja8d8e232005-06-07 20:04:56 +00001818//zz // (__NR_sgetmask, sys_sgetmask), // 68 */* (ANSI C)
1819//zz // (__NR_ssetmask, sys_ssetmask), // 69 */* (ANSI C)
1820//zz
njna3b67b72005-08-26 04:27:54 +00001821 LINX_(__NR_setreuid, sys_setreuid16), // 70
1822 LINX_(__NR_setregid, sys_setregid16), // 71
sewardja8d8e232005-06-07 20:04:56 +00001823//zz GENX_(__NR_sigsuspend, sys_sigsuspend), // 72
njncd405ea2005-08-31 02:44:31 +00001824 LINXY(__NR_sigpending, sys_sigpending), // 73
sewardja8d8e232005-06-07 20:04:56 +00001825//zz // (__NR_sethostname, sys_sethostname), // 74 */*
1826//zz
nethercote3d5e9102004-11-17 18:22:38 +00001827 GENX_(__NR_setrlimit, sys_setrlimit), // 75
sewardj696c5512005-06-08 23:38:32 +00001828 GENXY(__NR_getrlimit, sys_old_getrlimit), // 76
1829 GENXY(__NR_getrusage, sys_getrusage), // 77
nethercote3d5e9102004-11-17 18:22:38 +00001830 GENXY(__NR_gettimeofday, sys_gettimeofday), // 78
sewardj696c5512005-06-08 23:38:32 +00001831 GENX_(__NR_settimeofday, sys_settimeofday), // 79
1832
njna3b67b72005-08-26 04:27:54 +00001833 LINXY(__NR_getgroups, sys_getgroups16), // 80
1834 LINX_(__NR_setgroups, sys_setgroups16), // 81
sewardj696c5512005-06-08 23:38:32 +00001835 PLAX_(__NR_select, old_select), // 82
sewardj78b50e42005-06-08 01:47:28 +00001836 GENX_(__NR_symlink, sys_symlink), // 83
sewardja8d8e232005-06-07 20:04:56 +00001837//zz // (__NR_oldlstat, sys_lstat), // 84 -- obsolete
1838//zz
rjwalsh17d85302004-11-18 22:56:09 +00001839 GENX_(__NR_readlink, sys_readlink), // 85
sewardja8d8e232005-06-07 20:04:56 +00001840//zz // (__NR_uselib, sys_uselib), // 86 */Linux
1841//zz // (__NR_swapon, sys_swapon), // 87 */Linux
1842//zz // (__NR_reboot, sys_reboot), // 88 */Linux
1843//zz // (__NR_readdir, old_readdir), // 89 -- superseded
1844//zz
1845 PLAX_(__NR_mmap, old_mmap), // 90
nethercote8ff888f2004-11-17 17:11:45 +00001846 GENXY(__NR_munmap, sys_munmap), // 91
sewardj696c5512005-06-08 23:38:32 +00001847 GENX_(__NR_truncate, sys_truncate), // 92
sewardj8c257322005-06-08 01:01:48 +00001848 GENX_(__NR_ftruncate, sys_ftruncate), // 93
sewardj696c5512005-06-08 23:38:32 +00001849 GENX_(__NR_fchmod, sys_fchmod), // 94
1850
njnefc957c2005-08-26 04:36:10 +00001851 LINX_(__NR_fchown, sys_fchown16), // 95
sewardj696c5512005-06-08 23:38:32 +00001852 GENX_(__NR_getpriority, sys_getpriority), // 96
1853 GENX_(__NR_setpriority, sys_setpriority), // 97
nethercote3d5e9102004-11-17 18:22:38 +00001854 GENX_(__NR_profil, sys_ni_syscall), // 98
sewardj696c5512005-06-08 23:38:32 +00001855 GENXY(__NR_statfs, sys_statfs), // 99
1856
1857 GENXY(__NR_fstatfs, sys_fstatfs), // 100
1858 LINX_(__NR_ioperm, sys_ioperm), // 101
sewardja8d8e232005-06-07 20:04:56 +00001859 PLAXY(__NR_socketcall, sys_socketcall), // 102 x86/Linux-only
sewardj696c5512005-06-08 23:38:32 +00001860 LINXY(__NR_syslog, sys_syslog), // 103
1861 GENXY(__NR_setitimer, sys_setitimer), // 104
1862
1863 GENXY(__NR_getitimer, sys_getitimer), // 105
1864 GENXY(__NR_stat, sys_newstat), // 106
1865 GENXY(__NR_lstat, sys_newlstat), // 107
1866 GENXY(__NR_fstat, sys_newfstat), // 108
sewardja8d8e232005-06-07 20:04:56 +00001867//zz // (__NR_olduname, sys_uname), // 109 -- obsolete
1868//zz
sewardj696c5512005-06-08 23:38:32 +00001869 GENX_(__NR_iopl, sys_iopl), // 110
1870 LINX_(__NR_vhangup, sys_vhangup), // 111
nethercote3d5e9102004-11-17 18:22:38 +00001871 GENX_(__NR_idle, sys_ni_syscall), // 112
sewardja8d8e232005-06-07 20:04:56 +00001872//zz // (__NR_vm86old, sys_vm86old), // 113 x86/Linux-only
nethercote3d5e9102004-11-17 18:22:38 +00001873 GENXY(__NR_wait4, sys_wait4), // 114
sewardja8d8e232005-06-07 20:04:56 +00001874//zz
1875//zz // (__NR_swapoff, sys_swapoff), // 115 */Linux
sewardj696c5512005-06-08 23:38:32 +00001876 LINXY(__NR_sysinfo, sys_sysinfo), // 116
njnc6168192004-11-29 13:54:10 +00001877 PLAXY(__NR_ipc, sys_ipc), // 117
sewardj78b50e42005-06-08 01:47:28 +00001878 GENX_(__NR_fsync, sys_fsync), // 118
sewardjb5f6f512005-03-10 23:59:00 +00001879 PLAX_(__NR_sigreturn, sys_sigreturn), // 119 ?/Linux
nethercote8ff888f2004-11-17 17:11:45 +00001880
nethercote3d5e9102004-11-17 18:22:38 +00001881 PLAX_(__NR_clone, sys_clone), // 120
sewardja8d8e232005-06-07 20:04:56 +00001882//zz // (__NR_setdomainname, sys_setdomainname), // 121 */*(?)
nethercote3d5e9102004-11-17 18:22:38 +00001883 GENXY(__NR_uname, sys_newuname), // 122
1884 PLAX_(__NR_modify_ldt, sys_modify_ldt), // 123
sewardja8d8e232005-06-07 20:04:56 +00001885//zz LINXY(__NR_adjtimex, sys_adjtimex), // 124
1886//zz
nethercote3d5e9102004-11-17 18:22:38 +00001887 GENXY(__NR_mprotect, sys_mprotect), // 125
njncd405ea2005-08-31 02:44:31 +00001888 LINXY(__NR_sigprocmask, sys_sigprocmask), // 126
sewardja8d8e232005-06-07 20:04:56 +00001889//zz // Nb: create_module() was removed 2.4-->2.6
nethercote3d5e9102004-11-17 18:22:38 +00001890 GENX_(__NR_create_module, sys_ni_syscall), // 127
sewardj696c5512005-06-08 23:38:32 +00001891 GENX_(__NR_init_module, sys_init_module), // 128
sewardja8d8e232005-06-07 20:04:56 +00001892//zz // (__NR_delete_module, sys_delete_module), // 129 (*/Linux)?
1893//zz
1894//zz // Nb: get_kernel_syms() was removed 2.4-->2.6
nethercote3d5e9102004-11-17 18:22:38 +00001895 GENX_(__NR_get_kernel_syms, sys_ni_syscall), // 130
njncd405ea2005-08-31 02:44:31 +00001896 LINX_(__NR_quotactl, sys_quotactl), // 131
sewardj696c5512005-06-08 23:38:32 +00001897 GENX_(__NR_getpgid, sys_getpgid), // 132
1898 GENX_(__NR_fchdir, sys_fchdir), // 133
sewardja8d8e232005-06-07 20:04:56 +00001899//zz // (__NR_bdflush, sys_bdflush), // 134 */Linux
1900//zz
1901//zz // (__NR_sysfs, sys_sysfs), // 135 SVr4
sewardj696c5512005-06-08 23:38:32 +00001902 LINX_(__NR_personality, sys_personality), // 136
nethercote3d5e9102004-11-17 18:22:38 +00001903 GENX_(__NR_afs_syscall, sys_ni_syscall), // 137
sewardj696c5512005-06-08 23:38:32 +00001904 LINX_(__NR_setfsuid, sys_setfsuid16), // 138
1905 LINX_(__NR_setfsgid, sys_setfsgid16), // 139
1906
nethercote8ff888f2004-11-17 17:11:45 +00001907 LINXY(__NR__llseek, sys_llseek), // 140
sewardj78b50e42005-06-08 01:47:28 +00001908 GENXY(__NR_getdents, sys_getdents), // 141
nethercote3d5e9102004-11-17 18:22:38 +00001909 GENX_(__NR__newselect, sys_select), // 142
sewardj696c5512005-06-08 23:38:32 +00001910 GENX_(__NR_flock, sys_flock), // 143
1911 GENX_(__NR_msync, sys_msync), // 144
1912
nethercote3d5e9102004-11-17 18:22:38 +00001913 GENXY(__NR_readv, sys_readv), // 145
1914 GENX_(__NR_writev, sys_writev), // 146
sewardj696c5512005-06-08 23:38:32 +00001915 GENX_(__NR_getsid, sys_getsid), // 147
1916 GENX_(__NR_fdatasync, sys_fdatasync), // 148
nethercote8ff888f2004-11-17 17:11:45 +00001917 LINXY(__NR__sysctl, sys_sysctl), // 149
sewardj696c5512005-06-08 23:38:32 +00001918
1919 GENX_(__NR_mlock, sys_mlock), // 150
1920 GENX_(__NR_munlock, sys_munlock), // 151
1921 GENX_(__NR_mlockall, sys_mlockall), // 152
njncd405ea2005-08-31 02:44:31 +00001922 LINX_(__NR_munlockall, sys_munlockall), // 153
njnb2480c92005-08-30 02:17:23 +00001923 LINXY(__NR_sched_setparam, sys_sched_setparam), // 154
sewardje6d5e722005-06-10 10:27:55 +00001924
njnb2480c92005-08-30 02:17:23 +00001925 LINXY(__NR_sched_getparam, sys_sched_getparam), // 155
1926 LINX_(__NR_sched_setscheduler, sys_sched_setscheduler), // 156
1927 LINX_(__NR_sched_getscheduler, sys_sched_getscheduler), // 157
1928 LINX_(__NR_sched_yield, sys_sched_yield), // 158
1929 LINX_(__NR_sched_get_priority_max, sys_sched_get_priority_max),// 159
sewardj78b50e42005-06-08 01:47:28 +00001930
njnb2480c92005-08-30 02:17:23 +00001931 LINX_(__NR_sched_get_priority_min, sys_sched_get_priority_min),// 160
1932//zz //LINX?(__NR_sched_rr_get_interval, sys_sched_rr_get_interval), // 161 */*
nethercote8ff888f2004-11-17 17:11:45 +00001933 GENXY(__NR_nanosleep, sys_nanosleep), // 162
1934 GENX_(__NR_mremap, sys_mremap), // 163
sewardje6d5e722005-06-10 10:27:55 +00001935 LINX_(__NR_setresuid, sys_setresuid16), // 164
1936
1937 LINXY(__NR_getresuid, sys_getresuid16), // 165
sewardja8d8e232005-06-07 20:04:56 +00001938//zz // (__NR_vm86, sys_vm86), // 166 x86/Linux-only
nethercote3d5e9102004-11-17 18:22:38 +00001939 GENX_(__NR_query_module, sys_ni_syscall), // 167
1940 GENXY(__NR_poll, sys_poll), // 168
sewardja8d8e232005-06-07 20:04:56 +00001941//zz // (__NR_nfsservctl, sys_nfsservctl), // 169 */Linux
1942//zz
sewardje6d5e722005-06-10 10:27:55 +00001943 LINX_(__NR_setresgid, sys_setresgid16), // 170
1944 LINXY(__NR_getresgid, sys_getresgid16), // 171
1945 LINX_(__NR_prctl, sys_prctl), // 172
sewardjd571aff2005-03-15 14:47:30 +00001946 PLAX_(__NR_rt_sigreturn, sys_rt_sigreturn), // 173 x86/Linux only?
njncd405ea2005-08-31 02:44:31 +00001947 LINXY(__NR_rt_sigaction, sys_rt_sigaction), // 174
nethercote8ff888f2004-11-17 17:11:45 +00001948
njncd405ea2005-08-31 02:44:31 +00001949 LINXY(__NR_rt_sigprocmask, sys_rt_sigprocmask), // 175
1950 LINXY(__NR_rt_sigpending, sys_rt_sigpending), // 176
1951 LINXY(__NR_rt_sigtimedwait, sys_rt_sigtimedwait),// 177
1952 LINXY(__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo),// 178
1953 LINX_(__NR_rt_sigsuspend, sys_rt_sigsuspend), // 179
sewardje6d5e722005-06-10 10:27:55 +00001954
1955 GENXY(__NR_pread64, sys_pread64), // 180
1956 GENX_(__NR_pwrite64, sys_pwrite64), // 181
njnefc957c2005-08-26 04:36:10 +00001957 LINX_(__NR_chown, sys_chown16), // 182
nethercote3d5e9102004-11-17 18:22:38 +00001958 GENXY(__NR_getcwd, sys_getcwd), // 183
njn9fe7b122005-08-26 04:03:04 +00001959 LINXY(__NR_capget, sys_capget), // 184
sewardje6d5e722005-06-10 10:27:55 +00001960
njn9fe7b122005-08-26 04:03:04 +00001961 LINX_(__NR_capset, sys_capset), // 185
nethercote3d5e9102004-11-17 18:22:38 +00001962 GENXY(__NR_sigaltstack, sys_sigaltstack), // 186
sewardje6d5e722005-06-10 10:27:55 +00001963 LINXY(__NR_sendfile, sys_sendfile), // 187
1964 GENXY(__NR_getpmsg, sys_getpmsg), // 188
1965 GENX_(__NR_putpmsg, sys_putpmsg), // 189
nethercote8ff888f2004-11-17 17:11:45 +00001966
sewardjc93d7b62005-03-12 20:45:56 +00001967 // Nb: we treat vfork as fork
1968 GENX_(__NR_vfork, sys_fork), // 190
nethercote3d5e9102004-11-17 18:22:38 +00001969 GENXY(__NR_ugetrlimit, sys_getrlimit), // 191
tom9548a162005-09-30 08:07:53 +00001970 PLAX_(__NR_mmap2, sys_mmap2), // 192
sewardje6d5e722005-06-10 10:27:55 +00001971 GENX_(__NR_truncate64, sys_truncate64), // 193
1972 GENX_(__NR_ftruncate64, sys_ftruncate64), // 194
1973
sewardja8d8e232005-06-07 20:04:56 +00001974 PLAXY(__NR_stat64, sys_stat64), // 195
1975 PLAXY(__NR_lstat64, sys_lstat64), // 196
1976 PLAXY(__NR_fstat64, sys_fstat64), // 197
sewardje6d5e722005-06-10 10:27:55 +00001977 GENX_(__NR_lchown32, sys_lchown), // 198
nethercote8ff888f2004-11-17 17:11:45 +00001978 GENX_(__NR_getuid32, sys_getuid), // 199
sewardj78b50e42005-06-08 01:47:28 +00001979
1980 GENX_(__NR_getgid32, sys_getgid), // 200
nethercote8ff888f2004-11-17 17:11:45 +00001981 GENX_(__NR_geteuid32, sys_geteuid), // 201
sewardj78b50e42005-06-08 01:47:28 +00001982 GENX_(__NR_getegid32, sys_getegid), // 202
sewardje6d5e722005-06-10 10:27:55 +00001983 GENX_(__NR_setreuid32, sys_setreuid), // 203
1984 GENX_(__NR_setregid32, sys_setregid), // 204
sewardj78b50e42005-06-08 01:47:28 +00001985
1986 GENXY(__NR_getgroups32, sys_getgroups), // 205
sewardje6d5e722005-06-10 10:27:55 +00001987 GENX_(__NR_setgroups32, sys_setgroups), // 206
1988 GENX_(__NR_fchown32, sys_fchown), // 207
1989 LINX_(__NR_setresuid32, sys_setresuid), // 208
sewardj78b50e42005-06-08 01:47:28 +00001990 LINXY(__NR_getresuid32, sys_getresuid), // 209
1991
sewardje6d5e722005-06-10 10:27:55 +00001992 LINX_(__NR_setresgid32, sys_setresgid), // 210
sewardj78b50e42005-06-08 01:47:28 +00001993 LINXY(__NR_getresgid32, sys_getresgid), // 211
sewardje6d5e722005-06-10 10:27:55 +00001994 GENX_(__NR_chown32, sys_chown), // 212
1995 GENX_(__NR_setuid32, sys_setuid), // 213
1996 GENX_(__NR_setgid32, sys_setgid), // 214
1997
1998 LINX_(__NR_setfsuid32, sys_setfsuid), // 215
1999 LINX_(__NR_setfsgid32, sys_setfsgid), // 216
sewardja8d8e232005-06-07 20:04:56 +00002000//zz // (__NR_pivot_root, sys_pivot_root), // 217 */Linux
sewardje6d5e722005-06-10 10:27:55 +00002001 GENXY(__NR_mincore, sys_mincore), // 218
nethercote3d5e9102004-11-17 18:22:38 +00002002 GENX_(__NR_madvise, sys_madvise), // 219
nethercote8ff888f2004-11-17 17:11:45 +00002003
nethercote3d5e9102004-11-17 18:22:38 +00002004 GENXY(__NR_getdents64, sys_getdents64), // 220
2005 GENXY(__NR_fcntl64, sys_fcntl64), // 221
2006 GENX_(222, sys_ni_syscall), // 222
sewardjce5a5662005-10-06 03:19:49 +00002007 PLAXY(223, sys_syscall223), // 223 // sys_bproc?
sewardj8c257322005-06-08 01:01:48 +00002008 LINX_(__NR_gettid, sys_gettid), // 224
2009
sewardja8d8e232005-06-07 20:04:56 +00002010//zz // (__NR_readahead, sys_readahead), // 225 */(Linux?)
njn65ccc502005-08-30 01:53:54 +00002011 LINX_(__NR_setxattr, sys_setxattr), // 226
2012 LINX_(__NR_lsetxattr, sys_lsetxattr), // 227
2013 LINX_(__NR_fsetxattr, sys_fsetxattr), // 228
2014 LINXY(__NR_getxattr, sys_getxattr), // 229
sewardje6d5e722005-06-10 10:27:55 +00002015
njn65ccc502005-08-30 01:53:54 +00002016 LINXY(__NR_lgetxattr, sys_lgetxattr), // 230
2017 LINXY(__NR_fgetxattr, sys_fgetxattr), // 231
2018 LINXY(__NR_listxattr, sys_listxattr), // 232
2019 LINXY(__NR_llistxattr, sys_llistxattr), // 233
2020 LINXY(__NR_flistxattr, sys_flistxattr), // 234
sewardje6d5e722005-06-10 10:27:55 +00002021
njn65ccc502005-08-30 01:53:54 +00002022 LINX_(__NR_removexattr, sys_removexattr), // 235
2023 LINX_(__NR_lremovexattr, sys_lremovexattr), // 236
2024 LINX_(__NR_fremovexattr, sys_fremovexattr), // 237
sewardja8d8e232005-06-07 20:04:56 +00002025//zz LINX_(__NR_tkill, sys_tkill), // 238 */Linux
sewardje6d5e722005-06-10 10:27:55 +00002026 LINXY(__NR_sendfile64, sys_sendfile64), // 239
2027
sewardjbc22cf72005-06-08 00:02:49 +00002028 LINXY(__NR_futex, sys_futex), // 240
njnb2480c92005-08-30 02:17:23 +00002029 LINX_(__NR_sched_setaffinity, sys_sched_setaffinity), // 241
2030 LINXY(__NR_sched_getaffinity, sys_sched_getaffinity), // 242
sewardjbc22cf72005-06-08 00:02:49 +00002031 PLAX_(__NR_set_thread_area, sys_set_thread_area), // 243
sewardje6d5e722005-06-10 10:27:55 +00002032 PLAX_(__NR_get_thread_area, sys_get_thread_area), // 244
2033
sewardj45f4e7c2005-09-27 19:20:21 +00002034 LINXY(__NR_io_setup, sys_io_setup), // 245
sewardje6d5e722005-06-10 10:27:55 +00002035 LINX_(__NR_io_destroy, sys_io_destroy), // 246
2036 LINXY(__NR_io_getevents, sys_io_getevents), // 247
2037 LINX_(__NR_io_submit, sys_io_submit), // 248
2038 LINXY(__NR_io_cancel, sys_io_cancel), // 249
2039
tom72440832005-06-15 10:31:10 +00002040 LINX_(__NR_fadvise64, sys_fadvise64), // 250 */(Linux?)
nethercote3d5e9102004-11-17 18:22:38 +00002041 GENX_(251, sys_ni_syscall), // 251
sewardjb5f6f512005-03-10 23:59:00 +00002042 LINX_(__NR_exit_group, sys_exit_group), // 252
sewardje6d5e722005-06-10 10:27:55 +00002043 GENXY(__NR_lookup_dcookie, sys_lookup_dcookie), // 253
2044 LINXY(__NR_epoll_create, sys_epoll_create), // 254
2045
2046 LINX_(__NR_epoll_ctl, sys_epoll_ctl), // 255
2047 LINXY(__NR_epoll_wait, sys_epoll_wait), // 256
sewardja8d8e232005-06-07 20:04:56 +00002048//zz // (__NR_remap_file_pages, sys_remap_file_pages), // 257 */Linux
sewardjbc22cf72005-06-08 00:02:49 +00002049 LINX_(__NR_set_tid_address, sys_set_tid_address), // 258
njn424c0562005-08-26 03:54:30 +00002050 LINXY(__NR_timer_create, sys_timer_create), // 259
sewardje6d5e722005-06-10 10:27:55 +00002051
njn424c0562005-08-26 03:54:30 +00002052 LINXY(__NR_timer_settime, sys_timer_settime), // (timer_create+1)
2053 LINXY(__NR_timer_gettime, sys_timer_gettime), // (timer_create+2)
2054 LINX_(__NR_timer_getoverrun, sys_timer_getoverrun),//(timer_create+3)
2055 LINX_(__NR_timer_delete, sys_timer_delete), // (timer_create+4)
njn1588bc02005-08-26 03:49:43 +00002056 LINX_(__NR_clock_settime, sys_clock_settime), // (timer_create+5)
sewardje6d5e722005-06-10 10:27:55 +00002057
njn1588bc02005-08-26 03:49:43 +00002058 LINXY(__NR_clock_gettime, sys_clock_gettime), // (timer_create+6)
2059 LINXY(__NR_clock_getres, sys_clock_getres), // (timer_create+7)
2060 LINXY(__NR_clock_nanosleep, sys_clock_nanosleep),// (timer_create+8) */*
sewardje6d5e722005-06-10 10:27:55 +00002061 GENXY(__NR_statfs64, sys_statfs64), // 268
2062 GENXY(__NR_fstatfs64, sys_fstatfs64), // 269
2063
sewardjbc22cf72005-06-08 00:02:49 +00002064 LINX_(__NR_tgkill, sys_tgkill), // 270 */Linux
sewardje6d5e722005-06-10 10:27:55 +00002065 GENX_(__NR_utimes, sys_utimes), // 271
tom72440832005-06-15 10:31:10 +00002066 LINX_(__NR_fadvise64_64, sys_fadvise64_64), // 272 */(Linux?)
nethercote3d5e9102004-11-17 18:22:38 +00002067 GENX_(__NR_vserver, sys_ni_syscall), // 273
tom70a5cb02005-10-20 17:00:23 +00002068 LINX_(__NR_mbind, sys_mbind), // 274 ?/?
2069
tom2af58f22005-07-22 15:04:14 +00002070 LINXY(__NR_get_mempolicy, sys_get_mempolicy), // 275 ?/?
2071 LINX_(__NR_set_mempolicy, sys_set_mempolicy), // 276 ?/?
njn4279a882005-08-26 03:43:28 +00002072 LINXY(__NR_mq_open, sys_mq_open), // 277
2073 LINX_(__NR_mq_unlink, sys_mq_unlink), // (mq_open+1)
2074 LINX_(__NR_mq_timedsend, sys_mq_timedsend), // (mq_open+2)
sewardj8c9ea4e2005-06-08 10:46:56 +00002075
njn4279a882005-08-26 03:43:28 +00002076 LINXY(__NR_mq_timedreceive, sys_mq_timedreceive),// (mq_open+3)
2077 LINX_(__NR_mq_notify, sys_mq_notify), // (mq_open+4)
2078 LINXY(__NR_mq_getsetattr, sys_mq_getsetattr), // (mq_open+5)
nethercote8ff888f2004-11-17 17:11:45 +00002079 GENX_(__NR_sys_kexec_load, sys_ni_syscall), // 283
njncd405ea2005-08-31 02:44:31 +00002080 LINXY(__NR_waitid, sys_waitid), // 284
tom0bcaf2a2005-07-25 15:21:41 +00002081
2082 GENX_(285, sys_ni_syscall), // 285
2083// LINX_(__NR_add_key, sys_add_key), // 286
2084// LINX_(__NR_request_key, sys_request_key), // 287
2085// LINXY(__NR_keyctl, sys_keyctl), // 288
2086// LINX_(__NR_ioprio_set, sys_ioprio_set), // 289
2087
2088// LINX_(__NR_ioprio_get, sys_ioprio_get), // 290
2089 LINX_(__NR_inotify_init, sys_inotify_init), // 291
2090 LINX_(__NR_inotify_add_watch, sys_inotify_add_watch), // 292
2091 LINX_(__NR_inotify_rm_watch, sys_inotify_rm_watch), // 293
nethercote8ff888f2004-11-17 17:11:45 +00002092};
2093
njnaf839f52005-06-23 03:27:57 +00002094const UInt ML_(syscall_table_size) =
2095 sizeof(ML_(syscall_table)) / sizeof(ML_(syscall_table)[0]);
nethercote8ff888f2004-11-17 17:11:45 +00002096
nethercote41c75da2004-10-18 15:34:14 +00002097/*--------------------------------------------------------------------*/
2098/*--- end ---*/
2099/*--------------------------------------------------------------------*/