blob: a782af15d6427025265ffdfcdfb73996f0df8086 [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
sewardje4b0bf02006-06-05 23:21:15 +000010 Copyright (C) 2000-2006 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
sewardj4eee4762006-10-14 15:51:32 +000061#include "pub_core_vkiscnums.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);
tom363ec762006-03-21 10:58:35 +0000761DECL_TEMPLATE(x86_linux, sys_fstatat64);
sewardja8d8e232005-06-07 20:04:56 +0000762DECL_TEMPLATE(x86_linux, sys_fstat64);
763DECL_TEMPLATE(x86_linux, sys_lstat64);
764DECL_TEMPLATE(x86_linux, sys_clone);
765DECL_TEMPLATE(x86_linux, old_mmap);
tom9548a162005-09-30 08:07:53 +0000766DECL_TEMPLATE(x86_linux, sys_mmap2);
sewardja8d8e232005-06-07 20:04:56 +0000767DECL_TEMPLATE(x86_linux, sys_sigreturn);
768DECL_TEMPLATE(x86_linux, sys_ipc);
769DECL_TEMPLATE(x86_linux, sys_rt_sigreturn);
770DECL_TEMPLATE(x86_linux, sys_modify_ldt);
sewardjbc22cf72005-06-08 00:02:49 +0000771DECL_TEMPLATE(x86_linux, sys_set_thread_area);
sewardje6d5e722005-06-10 10:27:55 +0000772DECL_TEMPLATE(x86_linux, sys_get_thread_area);
sewardj8c257322005-06-08 01:01:48 +0000773DECL_TEMPLATE(x86_linux, sys_ptrace);
sewardj696c5512005-06-08 23:38:32 +0000774DECL_TEMPLATE(x86_linux, sys_sigaction);
tom313639f2006-04-03 16:38:33 +0000775DECL_TEMPLATE(x86_linux, sys_sigsuspend);
sewardj696c5512005-06-08 23:38:32 +0000776DECL_TEMPLATE(x86_linux, old_select);
tomc1369aa2006-02-11 16:26:46 +0000777DECL_TEMPLATE(x86_linux, sys_vm86old);
778DECL_TEMPLATE(x86_linux, sys_vm86);
sewardjce5a5662005-10-06 03:19:49 +0000779DECL_TEMPLATE(x86_linux, sys_syscall223);
nethercote8ff888f2004-11-17 17:11:45 +0000780
sewardj696c5512005-06-08 23:38:32 +0000781PRE(old_select)
782{
783 /* struct sel_arg_struct {
784 unsigned long n;
785 fd_set *inp, *outp, *exp;
786 struct timeval *tvp;
787 };
788 */
789 PRE_REG_READ1(long, "old_select", struct sel_arg_struct *, args);
790 PRE_MEM_READ( "old_select(args)", ARG1, 5*sizeof(UWord) );
791 *flags |= SfMayBlock;
792 {
793 UInt* arg_struct = (UInt*)ARG1;
794 UInt a1, a2, a3, a4, a5;
795
796 a1 = arg_struct[0];
797 a2 = arg_struct[1];
798 a3 = arg_struct[2];
799 a4 = arg_struct[3];
800 a5 = arg_struct[4];
801
802 PRINT("old_select ( %d, %p, %p, %p, %p )", a1,a2,a3,a4,a5);
803 if (a2 != (Addr)NULL)
804 PRE_MEM_READ( "old_select(readfds)", a2, a1/8 /* __FD_SETSIZE/8 */ );
805 if (a3 != (Addr)NULL)
806 PRE_MEM_READ( "old_select(writefds)", a3, a1/8 /* __FD_SETSIZE/8 */ );
807 if (a4 != (Addr)NULL)
808 PRE_MEM_READ( "old_select(exceptfds)", a4, a1/8 /* __FD_SETSIZE/8 */ );
809 if (a5 != (Addr)NULL)
810 PRE_MEM_READ( "old_select(timeout)", a5, sizeof(struct vki_timeval) );
811 }
812}
nethercote3d5e9102004-11-17 18:22:38 +0000813
sewardja8d8e232005-06-07 20:04:56 +0000814PRE(sys_clone)
nethercote3d5e9102004-11-17 18:22:38 +0000815{
sewardjb5f6f512005-03-10 23:59:00 +0000816 UInt cloneflags;
nethercote3d5e9102004-11-17 18:22:38 +0000817
sewardjb5f6f512005-03-10 23:59:00 +0000818 PRINT("sys_clone ( %x, %p, %p, %p, %p )",ARG1,ARG2,ARG3,ARG4,ARG5);
819 PRE_REG_READ5(int, "clone",
820 unsigned long, flags,
821 void *, child_stack,
822 int *, parent_tidptr,
823 vki_modify_ldt_t *, tlsinfo,
824 int *, child_tidptr);
825
826 if (ARG1 & VKI_CLONE_PARENT_SETTID) {
827 PRE_MEM_WRITE("clone(parent_tidptr)", ARG3, sizeof(Int));
sewardj45f4e7c2005-09-27 19:20:21 +0000828 if (!VG_(am_is_valid_for_client)(ARG3, sizeof(Int),
829 VKI_PROT_WRITE)) {
sewardja8d8e232005-06-07 20:04:56 +0000830 SET_STATUS_Failure( VKI_EFAULT );
sewardjb5f6f512005-03-10 23:59:00 +0000831 return;
832 }
nethercote3d5e9102004-11-17 18:22:38 +0000833 }
sewardjb5f6f512005-03-10 23:59:00 +0000834 if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID)) {
835 PRE_MEM_WRITE("clone(child_tidptr)", ARG5, sizeof(Int));
sewardj45f4e7c2005-09-27 19:20:21 +0000836 if (!VG_(am_is_valid_for_client)(ARG5, sizeof(Int),
837 VKI_PROT_WRITE)) {
sewardja8d8e232005-06-07 20:04:56 +0000838 SET_STATUS_Failure( VKI_EFAULT );
sewardjb5f6f512005-03-10 23:59:00 +0000839 return;
840 }
841 }
842 if (ARG1 & VKI_CLONE_SETTLS) {
843 PRE_MEM_READ("clone(tls_user_desc)", ARG4, sizeof(vki_modify_ldt_t));
sewardj45f4e7c2005-09-27 19:20:21 +0000844 if (!VG_(am_is_valid_for_client)(ARG4, sizeof(vki_modify_ldt_t),
845 VKI_PROT_READ)) {
sewardja8d8e232005-06-07 20:04:56 +0000846 SET_STATUS_Failure( VKI_EFAULT );
sewardjb5f6f512005-03-10 23:59:00 +0000847 return;
848 }
849 }
850
851 cloneflags = ARG1;
852
sewardj7eb7c582005-06-23 01:02:53 +0000853 if (!ML_(client_signal_OK)(ARG1 & VKI_CSIGNAL)) {
sewardja8d8e232005-06-07 20:04:56 +0000854 SET_STATUS_Failure( VKI_EINVAL );
sewardjb5f6f512005-03-10 23:59:00 +0000855 return;
856 }
857
sewardj468dc792005-05-31 10:12:06 +0000858 /* Be ultra-paranoid and filter out any clone-variants we don't understand:
859 - ??? specifies clone flags of 0x100011
860 - ??? specifies clone flags of 0x1200011.
861 - NPTL specifies clone flags of 0x7D0F00.
862 - The Quadrics Elan3 driver specifies clone flags of 0xF00.
sewardjde2b1602005-11-05 15:13:23 +0000863 - Newer Quadrics Elan3 drivers with NTPL support specify 0x410F00.
sewardj468dc792005-05-31 10:12:06 +0000864 Everything else is rejected.
865 */
sewardj934d2d52005-05-31 13:08:03 +0000866 if (
sewardjde2b1602005-11-05 15:13:23 +0000867 1 ||
868 /* 11 Nov 05: for the time being, disable this ultra-paranoia.
869 The switch below probably does a good enough job. */
sewardj934d2d52005-05-31 13:08:03 +0000870 (cloneflags == 0x100011 || cloneflags == 0x1200011
871 || cloneflags == 0x7D0F00
sewardja8d8e232005-06-07 20:04:56 +0000872 || cloneflags == 0x790F00
sewardjd15ce0c2005-05-31 21:07:01 +0000873 || cloneflags == 0x3D0F00
sewardjde2b1602005-11-05 15:13:23 +0000874 || cloneflags == 0x410F00
sewardj934d2d52005-05-31 13:08:03 +0000875 || cloneflags == 0xF00
876 || cloneflags == 0xF21)) {
877 /* OK */
sewardj468dc792005-05-31 10:12:06 +0000878 }
879 else {
880 /* Nah. We don't like it. Go away. */
881 goto reject;
882 }
883
sewardjb5f6f512005-03-10 23:59:00 +0000884 /* Only look at the flags we really care about */
sewardja8d8e232005-06-07 20:04:56 +0000885 switch (cloneflags & (VKI_CLONE_VM | VKI_CLONE_FS
886 | VKI_CLONE_FILES | VKI_CLONE_VFORK)) {
sewardjb5f6f512005-03-10 23:59:00 +0000887 case VKI_CLONE_VM | VKI_CLONE_FS | VKI_CLONE_FILES:
888 /* thread creation */
sewardja8d8e232005-06-07 20:04:56 +0000889 SET_STATUS_from_SysRes(
890 do_clone(tid,
891 ARG1, /* flags */
892 (Addr)ARG2, /* child ESP */
893 (Int *)ARG3, /* parent_tidptr */
894 (Int *)ARG5, /* child_tidptr */
895 (vki_modify_ldt_t *)ARG4)); /* set_tls */
sewardjb5f6f512005-03-10 23:59:00 +0000896 break;
897
898 case VKI_CLONE_VFORK | VKI_CLONE_VM: /* vfork */
899 /* FALLTHROUGH - assume vfork == fork */
900 cloneflags &= ~(VKI_CLONE_VFORK | VKI_CLONE_VM);
901
902 case 0: /* plain fork */
sewardja8d8e232005-06-07 20:04:56 +0000903 SET_STATUS_from_SysRes(
njne1486662005-11-10 02:48:04 +0000904 ML_(do_fork_clone)(tid,
sewardje7aa4ae2005-06-09 12:43:42 +0000905 cloneflags, /* flags */
sewardja8d8e232005-06-07 20:04:56 +0000906 (Int *)ARG3, /* parent_tidptr */
907 (Int *)ARG5)); /* child_tidptr */
sewardjb5f6f512005-03-10 23:59:00 +0000908 break;
909
910 default:
sewardj468dc792005-05-31 10:12:06 +0000911 reject:
sewardjb5f6f512005-03-10 23:59:00 +0000912 /* should we just ENOSYS? */
sewardj468dc792005-05-31 10:12:06 +0000913 VG_(message)(Vg_UserMsg, "");
914 VG_(message)(Vg_UserMsg, "Unsupported clone() flags: 0x%x", ARG1);
915 VG_(message)(Vg_UserMsg, "");
sewardj468dc792005-05-31 10:12:06 +0000916 VG_(message)(Vg_UserMsg, "The only supported clone() uses are:");
917 VG_(message)(Vg_UserMsg, " - via a threads library (LinuxThreads or NPTL)");
918 VG_(message)(Vg_UserMsg, " - via the implementation of fork or vfork");
919 VG_(message)(Vg_UserMsg, " - for the Quadrics Elan3 user-space driver");
sewardjb5f6f512005-03-10 23:59:00 +0000920 VG_(unimplemented)
sewardj468dc792005-05-31 10:12:06 +0000921 ("Valgrind does not support general clone().");
sewardjb5f6f512005-03-10 23:59:00 +0000922 }
923
sewardja8d8e232005-06-07 20:04:56 +0000924 if (SUCCESS) {
sewardjb5f6f512005-03-10 23:59:00 +0000925 if (ARG1 & VKI_CLONE_PARENT_SETTID)
926 POST_MEM_WRITE(ARG3, sizeof(Int));
927 if (ARG1 & (VKI_CLONE_CHILD_SETTID | VKI_CLONE_CHILD_CLEARTID))
928 POST_MEM_WRITE(ARG5, sizeof(Int));
929
930 /* Thread creation was successful; let the child have the chance
931 to run */
sewardja8d8e232005-06-07 20:04:56 +0000932 *flags |= SfYieldAfter;
sewardjb5f6f512005-03-10 23:59:00 +0000933 }
934}
935
sewardja8d8e232005-06-07 20:04:56 +0000936PRE(sys_sigreturn)
sewardjb5f6f512005-03-10 23:59:00 +0000937{
sewardja8d8e232005-06-07 20:04:56 +0000938 ThreadState* tst;
sewardjb5f6f512005-03-10 23:59:00 +0000939 PRINT("sigreturn ( )");
940
sewardja8d8e232005-06-07 20:04:56 +0000941 vg_assert(VG_(is_valid_tid)(tid));
942 vg_assert(tid >= 1 && tid < VG_N_THREADS);
943 vg_assert(VG_(is_running_thread)(tid));
944
sewardjb5f6f512005-03-10 23:59:00 +0000945 /* Adjust esp to point to start of frame; skip back up over
946 sigreturn sequence's "popl %eax" and handler ret addr */
sewardja8d8e232005-06-07 20:04:56 +0000947 tst = VG_(get_ThreadState)(tid);
sewardjb5f6f512005-03-10 23:59:00 +0000948 tst->arch.vex.guest_ESP -= sizeof(Addr)+sizeof(Word);
949
950 /* This is only so that the EIP is (might be) useful to report if
951 something goes wrong in the sigreturn */
sewardj7eb7c582005-06-23 01:02:53 +0000952 ML_(fixup_guest_state_to_restart_syscall)(&tst->arch);
sewardjb5f6f512005-03-10 23:59:00 +0000953
sewardj985fabb2005-04-24 14:18:14 +0000954 VG_(sigframe_destroy)(tid, False);
sewardjb5f6f512005-03-10 23:59:00 +0000955
sewardja8d8e232005-06-07 20:04:56 +0000956 /* For unclear reasons, it appears we need the syscall to return
957 without changing %EAX. Since %EAX is the return value, and can
958 denote either success or failure, we must set up so that the
959 driver logic copies it back unchanged. Also, note %EAX is of
960 the guest registers written by VG_(sigframe_destroy). */
cerion85665ca2005-06-20 15:51:07 +0000961 SET_STATUS_from_SysRes( VG_(mk_SysRes_x86_linux)( tst->arch.vex.guest_EAX ) );
sewardjb5f6f512005-03-10 23:59:00 +0000962
sewardja8d8e232005-06-07 20:04:56 +0000963 /* Check to see if some any signals arose as a result of this. */
964 *flags |= SfPollAfter;
nethercote3d5e9102004-11-17 18:22:38 +0000965}
966
sewardja8d8e232005-06-07 20:04:56 +0000967PRE(sys_rt_sigreturn)
sewardjd571aff2005-03-15 14:47:30 +0000968{
sewardja8d8e232005-06-07 20:04:56 +0000969 ThreadState* tst;
sewardjd571aff2005-03-15 14:47:30 +0000970 PRINT("rt_sigreturn ( )");
971
sewardja8d8e232005-06-07 20:04:56 +0000972 vg_assert(VG_(is_valid_tid)(tid));
973 vg_assert(tid >= 1 && tid < VG_N_THREADS);
974 vg_assert(VG_(is_running_thread)(tid));
975
sewardjd571aff2005-03-15 14:47:30 +0000976 /* Adjust esp to point to start of frame; skip back up over handler
977 ret addr */
sewardja8d8e232005-06-07 20:04:56 +0000978 tst = VG_(get_ThreadState)(tid);
sewardjd571aff2005-03-15 14:47:30 +0000979 tst->arch.vex.guest_ESP -= sizeof(Addr);
980
981 /* This is only so that the EIP is (might be) useful to report if
982 something goes wrong in the sigreturn */
sewardj7eb7c582005-06-23 01:02:53 +0000983 ML_(fixup_guest_state_to_restart_syscall)(&tst->arch);
sewardjd571aff2005-03-15 14:47:30 +0000984
sewardj5bcde922005-05-03 22:31:22 +0000985 VG_(sigframe_destroy)(tid, True);
sewardjd571aff2005-03-15 14:47:30 +0000986
sewardja8d8e232005-06-07 20:04:56 +0000987 /* For unclear reasons, it appears we need the syscall to return
988 without changing %EAX. Since %EAX is the return value, and can
989 denote either success or failure, we must set up so that the
990 driver logic copies it back unchanged. Also, note %EAX is of
991 the guest registers written by VG_(sigframe_destroy). */
cerion85665ca2005-06-20 15:51:07 +0000992 SET_STATUS_from_SysRes( VG_(mk_SysRes_x86_linux)( tst->arch.vex.guest_EAX ) );
sewardjd571aff2005-03-15 14:47:30 +0000993
sewardja8d8e232005-06-07 20:04:56 +0000994 /* Check to see if some any signals arose as a result of this. */
995 *flags |= SfPollAfter;
sewardjd571aff2005-03-15 14:47:30 +0000996}
997
sewardja8d8e232005-06-07 20:04:56 +0000998PRE(sys_modify_ldt)
nethercote8ff888f2004-11-17 17:11:45 +0000999{
njn22cfccb2004-11-27 16:10:23 +00001000 PRINT("sys_modify_ldt ( %d, %p, %d )", ARG1,ARG2,ARG3);
nethercote8ff888f2004-11-17 17:11:45 +00001001 PRE_REG_READ3(int, "modify_ldt", int, func, void *, ptr,
1002 unsigned long, bytecount);
1003
njn22cfccb2004-11-27 16:10:23 +00001004 if (ARG1 == 0) {
nethercote8ff888f2004-11-17 17:11:45 +00001005 /* read the LDT into ptr */
njn22cfccb2004-11-27 16:10:23 +00001006 PRE_MEM_WRITE( "modify_ldt(ptr)", ARG2, ARG3 );
nethercote8ff888f2004-11-17 17:11:45 +00001007 }
njn22cfccb2004-11-27 16:10:23 +00001008 if (ARG1 == 1 || ARG1 == 0x11) {
nethercote8ff888f2004-11-17 17:11:45 +00001009 /* write the LDT with the entry pointed at by ptr */
njn22cfccb2004-11-27 16:10:23 +00001010 PRE_MEM_READ( "modify_ldt(ptr)", ARG2, sizeof(vki_modify_ldt_t) );
nethercote8ff888f2004-11-17 17:11:45 +00001011 }
1012 /* "do" the syscall ourselves; the kernel never sees it */
sewardja8d8e232005-06-07 20:04:56 +00001013 SET_STATUS_from_SysRes( sys_modify_ldt( tid, ARG1, (void*)ARG2, ARG3 ) );
nethercote8ff888f2004-11-17 17:11:45 +00001014
sewardja8d8e232005-06-07 20:04:56 +00001015 if (ARG1 == 0 && SUCCESS && RES > 0) {
njn22cfccb2004-11-27 16:10:23 +00001016 POST_MEM_WRITE( ARG2, RES );
nethercote8ff888f2004-11-17 17:11:45 +00001017 }
1018}
1019
sewardjbc22cf72005-06-08 00:02:49 +00001020PRE(sys_set_thread_area)
1021{
1022 PRINT("sys_set_thread_area ( %p )", ARG1);
1023 PRE_REG_READ1(int, "set_thread_area", struct user_desc *, u_info)
1024 PRE_MEM_READ( "set_thread_area(u_info)", ARG1, sizeof(vki_modify_ldt_t) );
1025
1026 /* "do" the syscall ourselves; the kernel never sees it */
1027 SET_STATUS_from_SysRes( sys_set_thread_area( tid, (void *)ARG1 ) );
1028}
1029
sewardje6d5e722005-06-10 10:27:55 +00001030PRE(sys_get_thread_area)
1031{
1032 PRINT("sys_get_thread_area ( %p )", ARG1);
1033 PRE_REG_READ1(int, "get_thread_area", struct user_desc *, u_info)
1034 PRE_MEM_WRITE( "get_thread_area(u_info)", ARG1, sizeof(vki_modify_ldt_t) );
1035
1036 /* "do" the syscall ourselves; the kernel never sees it */
1037 SET_STATUS_from_SysRes( sys_get_thread_area( tid, (void *)ARG1 ) );
1038
1039 if (SUCCESS) {
1040 POST_MEM_WRITE( ARG1, sizeof(vki_modify_ldt_t) );
1041 }
1042}
sewardj8c257322005-06-08 01:01:48 +00001043
1044// Parts of this are x86-specific, but the *PEEK* cases are generic.
1045// XXX: Why is the memory pointed to by ARG3 never checked?
1046PRE(sys_ptrace)
1047{
1048 PRINT("sys_ptrace ( %d, %d, %p, %p )", ARG1,ARG2,ARG3,ARG4);
1049 PRE_REG_READ4(int, "ptrace",
1050 long, request, long, pid, long, addr, long, data);
1051 switch (ARG1) {
1052 case VKI_PTRACE_PEEKTEXT:
1053 case VKI_PTRACE_PEEKDATA:
1054 case VKI_PTRACE_PEEKUSR:
1055 PRE_MEM_WRITE( "ptrace(peek)", ARG4,
1056 sizeof (long));
1057 break;
1058 case VKI_PTRACE_GETREGS:
1059 PRE_MEM_WRITE( "ptrace(getregs)", ARG4,
1060 sizeof (struct vki_user_regs_struct));
1061 break;
1062 case VKI_PTRACE_GETFPREGS:
1063 PRE_MEM_WRITE( "ptrace(getfpregs)", ARG4,
1064 sizeof (struct vki_user_i387_struct));
1065 break;
1066 case VKI_PTRACE_GETFPXREGS:
1067 PRE_MEM_WRITE( "ptrace(getfpxregs)", ARG4,
1068 sizeof(struct vki_user_fxsr_struct) );
1069 break;
1070 case VKI_PTRACE_SETREGS:
1071 PRE_MEM_READ( "ptrace(setregs)", ARG4,
1072 sizeof (struct vki_user_regs_struct));
1073 break;
1074 case VKI_PTRACE_SETFPREGS:
1075 PRE_MEM_READ( "ptrace(setfpregs)", ARG4,
1076 sizeof (struct vki_user_i387_struct));
1077 break;
1078 case VKI_PTRACE_SETFPXREGS:
1079 PRE_MEM_READ( "ptrace(setfpxregs)", ARG4,
1080 sizeof(struct vki_user_fxsr_struct) );
1081 break;
1082 default:
1083 break;
1084 }
1085}
1086
1087POST(sys_ptrace)
1088{
1089 switch (ARG1) {
1090 case VKI_PTRACE_PEEKTEXT:
1091 case VKI_PTRACE_PEEKDATA:
1092 case VKI_PTRACE_PEEKUSR:
1093 POST_MEM_WRITE( ARG4, sizeof (long));
1094 break;
1095 case VKI_PTRACE_GETREGS:
1096 POST_MEM_WRITE( ARG4, sizeof (struct vki_user_regs_struct));
1097 break;
1098 case VKI_PTRACE_GETFPREGS:
1099 POST_MEM_WRITE( ARG4, sizeof (struct vki_user_i387_struct));
1100 break;
1101 case VKI_PTRACE_GETFPXREGS:
1102 POST_MEM_WRITE( ARG4, sizeof(struct vki_user_fxsr_struct) );
1103 break;
1104 default:
1105 break;
1106 }
1107}
njnca0518d2004-11-26 19:34:36 +00001108
njnb249fd72004-11-29 14:24:57 +00001109static Addr deref_Addr ( ThreadId tid, Addr a, Char* s )
1110{
1111 Addr* a_p = (Addr*)a;
1112 PRE_MEM_READ( s, (Addr)a_p, sizeof(Addr) );
1113 return *a_p;
1114}
njnc6168192004-11-29 13:54:10 +00001115
sewardja8d8e232005-06-07 20:04:56 +00001116PRE(sys_ipc)
njnc6168192004-11-29 13:54:10 +00001117{
1118 PRINT("sys_ipc ( %d, %d, %d, %d, %p, %d )", ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
1119 // XXX: this is simplistic -- some args are not used in all circumstances.
1120 PRE_REG_READ6(int, "ipc",
1121 vki_uint, call, int, first, int, second, int, third,
1122 void *, ptr, long, fifth)
1123
1124 switch (ARG1 /* call */) {
1125 case VKI_SEMOP:
sewardj7eb7c582005-06-23 01:02:53 +00001126 ML_(generic_PRE_sys_semop)( tid, ARG2, ARG5, ARG3 );
sewardja8d8e232005-06-07 20:04:56 +00001127 *flags |= SfMayBlock;
njnc6168192004-11-29 13:54:10 +00001128 break;
1129 case VKI_SEMGET:
1130 break;
1131 case VKI_SEMCTL:
1132 {
sewardjb369c5e2005-03-24 17:52:02 +00001133 UWord arg = deref_Addr( tid, ARG5, "semctl(arg)" );
sewardj7eb7c582005-06-23 01:02:53 +00001134 ML_(generic_PRE_sys_semctl)( tid, ARG2, ARG3, ARG4, arg );
njnc6168192004-11-29 13:54:10 +00001135 break;
1136 }
1137 case VKI_SEMTIMEDOP:
sewardj7eb7c582005-06-23 01:02:53 +00001138 ML_(generic_PRE_sys_semtimedop)( tid, ARG2, ARG5, ARG3, ARG6 );
sewardja8d8e232005-06-07 20:04:56 +00001139 *flags |= SfMayBlock;
njnc6168192004-11-29 13:54:10 +00001140 break;
1141 case VKI_MSGSND:
njncd405ea2005-08-31 02:44:31 +00001142 ML_(linux_PRE_sys_msgsnd)( tid, ARG2, ARG5, ARG3, ARG4 );
sewardja8d8e232005-06-07 20:04:56 +00001143 if ((ARG4 & VKI_IPC_NOWAIT) == 0)
1144 *flags |= SfMayBlock;
njnc6168192004-11-29 13:54:10 +00001145 break;
njnc6168192004-11-29 13:54:10 +00001146 case VKI_MSGRCV:
1147 {
sewardjb369c5e2005-03-24 17:52:02 +00001148 Addr msgp;
1149 Word msgtyp;
njnc6168192004-11-29 13:54:10 +00001150
sewardjb369c5e2005-03-24 17:52:02 +00001151 msgp = deref_Addr( tid,
1152 (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgp),
1153 "msgrcv(msgp)" );
1154 msgtyp = deref_Addr( tid,
1155 (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgtyp),
1156 "msgrcv(msgp)" );
njnc6168192004-11-29 13:54:10 +00001157
njncd405ea2005-08-31 02:44:31 +00001158 ML_(linux_PRE_sys_msgrcv)( tid, ARG2, msgp, ARG3, msgtyp, ARG4 );
njnc6168192004-11-29 13:54:10 +00001159
sewardja8d8e232005-06-07 20:04:56 +00001160 if ((ARG4 & VKI_IPC_NOWAIT) == 0)
1161 *flags |= SfMayBlock;
njnc6168192004-11-29 13:54:10 +00001162 break;
1163 }
1164 case VKI_MSGGET:
1165 break;
1166 case VKI_MSGCTL:
njncd405ea2005-08-31 02:44:31 +00001167 ML_(linux_PRE_sys_msgctl)( tid, ARG2, ARG3, ARG5 );
njnc6168192004-11-29 13:54:10 +00001168 break;
njnc6168192004-11-29 13:54:10 +00001169 case VKI_SHMAT:
sewardja8d8e232005-06-07 20:04:56 +00001170 {
1171 UWord w;
sewardjb369c5e2005-03-24 17:52:02 +00001172 PRE_MEM_WRITE( "shmat(raddr)", ARG4, sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001173 w = ML_(generic_PRE_sys_shmat)( tid, ARG2, ARG5, ARG3 );
sewardja8d8e232005-06-07 20:04:56 +00001174 if (w == 0)
1175 SET_STATUS_Failure( VKI_EINVAL );
1176 else
1177 ARG5 = w;
njnc6168192004-11-29 13:54:10 +00001178 break;
sewardja8d8e232005-06-07 20:04:56 +00001179 }
njnc6168192004-11-29 13:54:10 +00001180 case VKI_SHMDT:
sewardj7eb7c582005-06-23 01:02:53 +00001181 if (!ML_(generic_PRE_sys_shmdt)(tid, ARG5))
sewardja8d8e232005-06-07 20:04:56 +00001182 SET_STATUS_Failure( VKI_EINVAL );
njnc6168192004-11-29 13:54:10 +00001183 break;
1184 case VKI_SHMGET:
1185 break;
1186 case VKI_SHMCTL: /* IPCOP_shmctl */
sewardj7eb7c582005-06-23 01:02:53 +00001187 ML_(generic_PRE_sys_shmctl)( tid, ARG2, ARG3, ARG5 );
njnc6168192004-11-29 13:54:10 +00001188 break;
njnc6168192004-11-29 13:54:10 +00001189 default:
1190 VG_(message)(Vg_DebugMsg, "FATAL: unhandled syscall(ipc) %d", ARG1 );
1191 VG_(core_panic)("... bye!\n");
1192 break; /*NOTREACHED*/
1193 }
1194}
1195
1196POST(sys_ipc)
1197{
sewardja8d8e232005-06-07 20:04:56 +00001198 vg_assert(SUCCESS);
njnc6168192004-11-29 13:54:10 +00001199 switch (ARG1 /* call */) {
1200 case VKI_SEMOP:
1201 case VKI_SEMGET:
1202 break;
1203 case VKI_SEMCTL:
1204 {
sewardjb369c5e2005-03-24 17:52:02 +00001205 UWord arg = deref_Addr( tid, ARG5, "semctl(arg)" );
sewardj7eb7c582005-06-23 01:02:53 +00001206 ML_(generic_PRE_sys_semctl)( tid, ARG2, ARG3, ARG4, arg );
njnc6168192004-11-29 13:54:10 +00001207 break;
1208 }
1209 case VKI_SEMTIMEDOP:
1210 case VKI_MSGSND:
1211 break;
1212 case VKI_MSGRCV:
1213 {
sewardjb369c5e2005-03-24 17:52:02 +00001214 Addr msgp;
1215 Word msgtyp;
1216
1217 msgp = deref_Addr( tid,
1218 (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgp),
1219 "msgrcv(msgp)" );
1220 msgtyp = deref_Addr( tid,
1221 (Addr) (&((struct vki_ipc_kludge *)ARG5)->msgtyp),
1222 "msgrcv(msgp)" );
1223
njncd405ea2005-08-31 02:44:31 +00001224 ML_(linux_POST_sys_msgrcv)( tid, RES, ARG2, msgp, ARG3, msgtyp, ARG4 );
njnc6168192004-11-29 13:54:10 +00001225 break;
1226 }
1227 case VKI_MSGGET:
1228 break;
1229 case VKI_MSGCTL:
njncd405ea2005-08-31 02:44:31 +00001230 ML_(linux_POST_sys_msgctl)( tid, RES, ARG2, ARG3, ARG5 );
njnc6168192004-11-29 13:54:10 +00001231 break;
njnc6168192004-11-29 13:54:10 +00001232 case VKI_SHMAT:
1233 {
njnc6168192004-11-29 13:54:10 +00001234 Addr addr;
1235
1236 /* force readability. before the syscall it is
1237 * indeed uninitialized, as can be seen in
1238 * glibc/sysdeps/unix/sysv/linux/shmat.c */
sewardjb369c5e2005-03-24 17:52:02 +00001239 POST_MEM_WRITE( ARG4, sizeof( Addr ) );
njnc6168192004-11-29 13:54:10 +00001240
1241 addr = deref_Addr ( tid, ARG4, "shmat(addr)" );
1242 if ( addr > 0 ) {
sewardj7eb7c582005-06-23 01:02:53 +00001243 ML_(generic_POST_sys_shmat)( tid, addr, ARG2, ARG5, ARG3 );
njnc6168192004-11-29 13:54:10 +00001244 }
1245 break;
1246 }
1247 case VKI_SHMDT:
sewardj7eb7c582005-06-23 01:02:53 +00001248 ML_(generic_POST_sys_shmdt)( tid, RES, ARG5 );
njnc6168192004-11-29 13:54:10 +00001249 break;
njnc6168192004-11-29 13:54:10 +00001250 case VKI_SHMGET:
1251 break;
1252 case VKI_SHMCTL:
sewardj7eb7c582005-06-23 01:02:53 +00001253 ML_(generic_POST_sys_shmctl)( tid, RES, ARG2, ARG3, ARG5 );
njnc6168192004-11-29 13:54:10 +00001254 break;
njnc6168192004-11-29 13:54:10 +00001255 default:
1256 VG_(message)(Vg_DebugMsg,
1257 "FATAL: unhandled syscall(ipc) %d",
1258 ARG1 );
1259 VG_(core_panic)("... bye!\n");
1260 break; /*NOTREACHED*/
1261 }
1262}
1263
sewardja8d8e232005-06-07 20:04:56 +00001264PRE(old_mmap)
sewardjb5f6f512005-03-10 23:59:00 +00001265{
sewardja8d8e232005-06-07 20:04:56 +00001266 /* struct mmap_arg_struct {
1267 unsigned long addr;
1268 unsigned long len;
1269 unsigned long prot;
1270 unsigned long flags;
1271 unsigned long fd;
1272 unsigned long offset;
1273 }; */
1274 UWord a1, a2, a3, a4, a5, a6;
tom9548a162005-09-30 08:07:53 +00001275 SysRes r;
sewardja8d8e232005-06-07 20:04:56 +00001276
sewardje6d5e722005-06-10 10:27:55 +00001277 UWord* args = (UWord*)ARG1;
1278 PRE_REG_READ1(long, "old_mmap", struct mmap_arg_struct *, args);
1279 PRE_MEM_READ( "old_mmap(args)", (Addr)args, 6*sizeof(UWord) );
sewardja8d8e232005-06-07 20:04:56 +00001280
sewardj45f4e7c2005-09-27 19:20:21 +00001281 a1 = args[1-1];
1282 a2 = args[2-1];
1283 a3 = args[3-1];
1284 a4 = args[4-1];
1285 a5 = args[5-1];
1286 a6 = args[6-1];
sewardja8d8e232005-06-07 20:04:56 +00001287
1288 PRINT("old_mmap ( %p, %llu, %d, %d, %d, %d )",
1289 a1, (ULong)a2, a3, a4, a5, a6 );
1290
sewardj274461d2005-10-02 17:01:41 +00001291 r = ML_(generic_PRE_sys_mmap)( tid, a1, a2, a3, a4, a5, (Off64T)a6 );
tom9548a162005-09-30 08:07:53 +00001292 SET_STATUS_from_SysRes(r);
1293}
sewardja8d8e232005-06-07 20:04:56 +00001294
tom9548a162005-09-30 08:07:53 +00001295PRE(sys_mmap2)
1296{
1297 SysRes r;
sewardja8d8e232005-06-07 20:04:56 +00001298
tom9548a162005-09-30 08:07:53 +00001299 // Exactly like old_mmap() except:
1300 // - all 6 args are passed in regs, rather than in a memory-block.
1301 // - the file offset is specified in pagesize units rather than bytes,
1302 // so that it can be used for files bigger than 2^32 bytes.
1303 PRINT("sys_mmap2 ( %p, %llu, %d, %d, %d, %d )",
1304 ARG1, (ULong)ARG2, ARG3, ARG4, ARG5, ARG6 );
1305 PRE_REG_READ6(long, "mmap2",
1306 unsigned long, start, unsigned long, length,
1307 unsigned long, prot, unsigned long, flags,
1308 unsigned long, fd, unsigned long, offset);
sewardja8d8e232005-06-07 20:04:56 +00001309
sewardj274461d2005-10-02 17:01:41 +00001310 r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5,
1311 VKI_PAGE_SIZE * (Off64T)ARG6 );
tom9548a162005-09-30 08:07:53 +00001312 SET_STATUS_from_SysRes(r);
sewardjb5f6f512005-03-10 23:59:00 +00001313}
sewardja8d8e232005-06-07 20:04:56 +00001314
1315// XXX: lstat64/fstat64/stat64 are generic, but not necessarily
1316// applicable to every architecture -- I think only to 32-bit archs.
1317// We're going to need something like linux/core_os32.h for such
1318// things, eventually, I think. --njn
1319PRE(sys_lstat64)
njnc6168192004-11-29 13:54:10 +00001320{
sewardja8d8e232005-06-07 20:04:56 +00001321 PRINT("sys_lstat64 ( %p(%s), %p )",ARG1,ARG1,ARG2);
1322 PRE_REG_READ2(long, "lstat64", char *, file_name, struct stat64 *, buf);
1323 PRE_MEM_RASCIIZ( "lstat64(file_name)", ARG1 );
1324 PRE_MEM_WRITE( "lstat64(buf)", ARG2, sizeof(struct vki_stat64) );
1325}
sewardjb5f6f512005-03-10 23:59:00 +00001326
sewardja8d8e232005-06-07 20:04:56 +00001327POST(sys_lstat64)
1328{
1329 vg_assert(SUCCESS);
1330 if (RES == 0) {
1331 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
sewardjb5f6f512005-03-10 23:59:00 +00001332 }
njnc6168192004-11-29 13:54:10 +00001333}
1334
sewardja8d8e232005-06-07 20:04:56 +00001335PRE(sys_stat64)
njnc6168192004-11-29 13:54:10 +00001336{
sewardja170a3f2006-05-04 16:43:34 +00001337 PRINT("sys_stat64 ( %p(%s), %p )",ARG1,ARG1,ARG2);
sewardja8d8e232005-06-07 20:04:56 +00001338 PRE_REG_READ2(long, "stat64", char *, file_name, struct stat64 *, buf);
1339 PRE_MEM_RASCIIZ( "stat64(file_name)", ARG1 );
1340 PRE_MEM_WRITE( "stat64(buf)", ARG2, sizeof(struct vki_stat64) );
njnc6168192004-11-29 13:54:10 +00001341}
1342
sewardja8d8e232005-06-07 20:04:56 +00001343POST(sys_stat64)
1344{
1345 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
1346}
1347
tom363ec762006-03-21 10:58:35 +00001348PRE(sys_fstatat64)
1349{
1350 PRINT("sys_fstatat64 ( %d, %p(%s), %p )",ARG1,ARG2,ARG2,ARG3);
1351 PRE_REG_READ3(long, "fstatat64",
1352 int, dfd, char *, file_name, struct stat64 *, buf);
1353 PRE_MEM_RASCIIZ( "fstatat64(file_name)", ARG2 );
1354 PRE_MEM_WRITE( "fstatat64(buf)", ARG3, sizeof(struct vki_stat64) );
1355}
1356
1357POST(sys_fstatat64)
1358{
1359 POST_MEM_WRITE( ARG3, sizeof(struct vki_stat64) );
1360}
1361
sewardja8d8e232005-06-07 20:04:56 +00001362PRE(sys_fstat64)
1363{
1364 PRINT("sys_fstat64 ( %d, %p )",ARG1,ARG2);
1365 PRE_REG_READ2(long, "fstat64", unsigned long, fd, struct stat64 *, buf);
1366 PRE_MEM_WRITE( "fstat64(buf)", ARG2, sizeof(struct vki_stat64) );
1367}
1368
1369POST(sys_fstat64)
1370{
1371 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat64) );
1372}
1373
1374PRE(sys_socketcall)
1375{
1376# define ARG2_0 (((UWord*)ARG2)[0])
1377# define ARG2_1 (((UWord*)ARG2)[1])
1378# define ARG2_2 (((UWord*)ARG2)[2])
1379# define ARG2_3 (((UWord*)ARG2)[3])
1380# define ARG2_4 (((UWord*)ARG2)[4])
1381# define ARG2_5 (((UWord*)ARG2)[5])
1382
1383 *flags |= SfMayBlock;
1384 PRINT("sys_socketcall ( %d, %p )",ARG1,ARG2);
1385 PRE_REG_READ2(long, "socketcall", int, call, unsigned long *, args);
1386
1387 switch (ARG1 /* request */) {
1388
1389 case VKI_SYS_SOCKETPAIR:
1390 /* int socketpair(int d, int type, int protocol, int sv[2]); */
1391 PRE_MEM_READ( "socketcall.socketpair(args)", ARG2, 4*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001392 ML_(generic_PRE_sys_socketpair)( tid, ARG2_0, ARG2_1, ARG2_2, ARG2_3 );
sewardja8d8e232005-06-07 20:04:56 +00001393 break;
1394
1395 case VKI_SYS_SOCKET:
1396 /* int socket(int domain, int type, int protocol); */
1397 PRE_MEM_READ( "socketcall.socket(args)", ARG2, 3*sizeof(Addr) );
1398 break;
1399
1400 case VKI_SYS_BIND:
1401 /* int bind(int sockfd, struct sockaddr *my_addr,
1402 int addrlen); */
1403 PRE_MEM_READ( "socketcall.bind(args)", ARG2, 3*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001404 ML_(generic_PRE_sys_bind)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001405 break;
1406
1407 case VKI_SYS_LISTEN:
1408 /* int listen(int s, int backlog); */
1409 PRE_MEM_READ( "socketcall.listen(args)", ARG2, 2*sizeof(Addr) );
1410 break;
1411
1412 case VKI_SYS_ACCEPT: {
1413 /* int accept(int s, struct sockaddr *addr, int *addrlen); */
1414 PRE_MEM_READ( "socketcall.accept(args)", ARG2, 3*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001415 ML_(generic_PRE_sys_accept)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001416 break;
1417 }
1418
1419 case VKI_SYS_SENDTO:
1420 /* int sendto(int s, const void *msg, int len,
1421 unsigned int flags,
1422 const struct sockaddr *to, int tolen); */
1423 PRE_MEM_READ( "socketcall.sendto(args)", ARG2, 6*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001424 ML_(generic_PRE_sys_sendto)( tid, ARG2_0, ARG2_1, ARG2_2,
sewardja8d8e232005-06-07 20:04:56 +00001425 ARG2_3, ARG2_4, ARG2_5 );
1426 break;
1427
1428 case VKI_SYS_SEND:
1429 /* int send(int s, const void *msg, size_t len, int flags); */
1430 PRE_MEM_READ( "socketcall.send(args)", ARG2, 4*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001431 ML_(generic_PRE_sys_send)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001432 break;
1433
1434 case VKI_SYS_RECVFROM:
1435 /* int recvfrom(int s, void *buf, int len, unsigned int flags,
1436 struct sockaddr *from, int *fromlen); */
1437 PRE_MEM_READ( "socketcall.recvfrom(args)", ARG2, 6*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001438 ML_(generic_PRE_sys_recvfrom)( tid, ARG2_0, ARG2_1, ARG2_2,
sewardja8d8e232005-06-07 20:04:56 +00001439 ARG2_3, ARG2_4, ARG2_5 );
1440 break;
1441
1442 case VKI_SYS_RECV:
1443 /* int recv(int s, void *buf, int len, unsigned int flags); */
1444 /* man 2 recv says:
1445 The recv call is normally used only on a connected socket
1446 (see connect(2)) and is identical to recvfrom with a NULL
1447 from parameter.
1448 */
1449 PRE_MEM_READ( "socketcall.recv(args)", ARG2, 4*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001450 ML_(generic_PRE_sys_recv)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001451 break;
1452
1453 case VKI_SYS_CONNECT:
1454 /* int connect(int sockfd,
1455 struct sockaddr *serv_addr, int addrlen ); */
1456 PRE_MEM_READ( "socketcall.connect(args)", ARG2, 3*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001457 ML_(generic_PRE_sys_connect)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001458 break;
1459
1460 case VKI_SYS_SETSOCKOPT:
1461 /* int setsockopt(int s, int level, int optname,
1462 const void *optval, int optlen); */
1463 PRE_MEM_READ( "socketcall.setsockopt(args)", ARG2, 5*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001464 ML_(generic_PRE_sys_setsockopt)( tid, ARG2_0, ARG2_1, ARG2_2,
sewardja8d8e232005-06-07 20:04:56 +00001465 ARG2_3, ARG2_4 );
1466 break;
1467
1468 case VKI_SYS_GETSOCKOPT:
1469 /* int getsockopt(int s, int level, int optname,
1470 void *optval, socklen_t *optlen); */
1471 PRE_MEM_READ( "socketcall.getsockopt(args)", ARG2, 5*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001472 ML_(generic_PRE_sys_getsockopt)( tid, ARG2_0, ARG2_1, ARG2_2,
sewardja8d8e232005-06-07 20:04:56 +00001473 ARG2_3, ARG2_4 );
1474 break;
1475
1476 case VKI_SYS_GETSOCKNAME:
1477 /* int getsockname(int s, struct sockaddr* name, int* namelen) */
1478 PRE_MEM_READ( "socketcall.getsockname(args)", ARG2, 3*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001479 ML_(generic_PRE_sys_getsockname)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001480 break;
1481
1482 case VKI_SYS_GETPEERNAME:
1483 /* int getpeername(int s, struct sockaddr* name, int* namelen) */
1484 PRE_MEM_READ( "socketcall.getpeername(args)", ARG2, 3*sizeof(Addr) );
sewardj7eb7c582005-06-23 01:02:53 +00001485 ML_(generic_PRE_sys_getpeername)( tid, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001486 break;
1487
1488 case VKI_SYS_SHUTDOWN:
1489 /* int shutdown(int s, int how); */
1490 PRE_MEM_READ( "socketcall.shutdown(args)", ARG2, 2*sizeof(Addr) );
1491 break;
1492
1493 case VKI_SYS_SENDMSG: {
1494 /* int sendmsg(int s, const struct msghdr *msg, int flags); */
1495
1496 /* this causes warnings, and I don't get why. glibc bug?
1497 * (after all it's glibc providing the arguments array)
1498 PRE_MEM_READ( "socketcall.sendmsg(args)", ARG2, 3*sizeof(Addr) );
1499 */
sewardj7eb7c582005-06-23 01:02:53 +00001500 ML_(generic_PRE_sys_sendmsg)( tid, ARG2_0, ARG2_1 );
sewardja8d8e232005-06-07 20:04:56 +00001501 break;
1502 }
1503
1504 case VKI_SYS_RECVMSG: {
1505 /* int recvmsg(int s, struct msghdr *msg, int flags); */
1506
1507 /* this causes warnings, and I don't get why. glibc bug?
1508 * (after all it's glibc providing the arguments array)
1509 PRE_MEM_READ("socketcall.recvmsg(args)", ARG2, 3*sizeof(Addr) );
1510 */
sewardj7eb7c582005-06-23 01:02:53 +00001511 ML_(generic_PRE_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
sewardja8d8e232005-06-07 20:04:56 +00001512 break;
1513 }
1514
1515 default:
1516 VG_(message)(Vg_DebugMsg,"Warning: unhandled socketcall 0x%x",ARG1);
1517 SET_STATUS_Failure( VKI_EINVAL );
1518 break;
1519 }
1520# undef ARG2_0
1521# undef ARG2_1
1522# undef ARG2_2
1523# undef ARG2_3
1524# undef ARG2_4
1525# undef ARG2_5
1526}
1527
1528POST(sys_socketcall)
1529{
1530# define ARG2_0 (((UWord*)ARG2)[0])
1531# define ARG2_1 (((UWord*)ARG2)[1])
1532# define ARG2_2 (((UWord*)ARG2)[2])
1533# define ARG2_3 (((UWord*)ARG2)[3])
1534# define ARG2_4 (((UWord*)ARG2)[4])
1535# define ARG2_5 (((UWord*)ARG2)[5])
1536
1537 SysRes r;
1538 vg_assert(SUCCESS);
1539 switch (ARG1 /* request */) {
1540
1541 case VKI_SYS_SOCKETPAIR:
sewardj7eb7c582005-06-23 01:02:53 +00001542 r = ML_(generic_POST_sys_socketpair)(
sewardja8d8e232005-06-07 20:04:56 +00001543 tid, VG_(mk_SysRes_Success)(RES),
1544 ARG2_0, ARG2_1, ARG2_2, ARG2_3
1545 );
1546 SET_STATUS_from_SysRes(r);
1547 break;
1548
1549 case VKI_SYS_SOCKET:
sewardj7eb7c582005-06-23 01:02:53 +00001550 r = ML_(generic_POST_sys_socket)( tid, VG_(mk_SysRes_Success)(RES) );
sewardja8d8e232005-06-07 20:04:56 +00001551 SET_STATUS_from_SysRes(r);
1552 break;
1553
1554 case VKI_SYS_BIND:
1555 /* int bind(int sockfd, struct sockaddr *my_addr,
1556 int addrlen); */
1557 break;
1558
1559 case VKI_SYS_LISTEN:
1560 /* int listen(int s, int backlog); */
1561 break;
1562
1563 case VKI_SYS_ACCEPT:
1564 /* int accept(int s, struct sockaddr *addr, int *addrlen); */
sewardj7eb7c582005-06-23 01:02:53 +00001565 r = ML_(generic_POST_sys_accept)( tid, VG_(mk_SysRes_Success)(RES),
sewardja8d8e232005-06-07 20:04:56 +00001566 ARG2_0, ARG2_1, ARG2_2 );
1567 SET_STATUS_from_SysRes(r);
1568 break;
1569
1570 case VKI_SYS_SENDTO:
1571 break;
1572
1573 case VKI_SYS_SEND:
1574 break;
1575
1576 case VKI_SYS_RECVFROM:
sewardj7eb7c582005-06-23 01:02:53 +00001577 ML_(generic_POST_sys_recvfrom)( tid, VG_(mk_SysRes_Success)(RES),
sewardja8d8e232005-06-07 20:04:56 +00001578 ARG2_0, ARG2_1, ARG2_2,
1579 ARG2_3, ARG2_4, ARG2_5 );
1580 break;
1581
1582 case VKI_SYS_RECV:
sewardj7eb7c582005-06-23 01:02:53 +00001583 ML_(generic_POST_sys_recv)( tid, RES, ARG2_0, ARG2_1, ARG2_2 );
sewardja8d8e232005-06-07 20:04:56 +00001584 break;
1585
1586 case VKI_SYS_CONNECT:
1587 break;
1588
1589 case VKI_SYS_SETSOCKOPT:
1590 break;
1591
1592 case VKI_SYS_GETSOCKOPT:
sewardj7eb7c582005-06-23 01:02:53 +00001593 ML_(generic_POST_sys_getsockopt)( tid, VG_(mk_SysRes_Success)(RES),
sewardja8d8e232005-06-07 20:04:56 +00001594 ARG2_0, ARG2_1,
1595 ARG2_2, ARG2_3, ARG2_4 );
1596 break;
1597
1598 case VKI_SYS_GETSOCKNAME:
sewardj7eb7c582005-06-23 01:02:53 +00001599 ML_(generic_POST_sys_getsockname)( tid, VG_(mk_SysRes_Success)(RES),
sewardja8d8e232005-06-07 20:04:56 +00001600 ARG2_0, ARG2_1, ARG2_2 );
1601 break;
1602
1603 case VKI_SYS_GETPEERNAME:
sewardj7eb7c582005-06-23 01:02:53 +00001604 ML_(generic_POST_sys_getpeername)( tid, VG_(mk_SysRes_Success)(RES),
sewardja8d8e232005-06-07 20:04:56 +00001605 ARG2_0, ARG2_1, ARG2_2 );
1606 break;
1607
1608 case VKI_SYS_SHUTDOWN:
1609 break;
1610
1611 case VKI_SYS_SENDMSG:
1612 break;
1613
1614 case VKI_SYS_RECVMSG:
sewardj7eb7c582005-06-23 01:02:53 +00001615 ML_(generic_POST_sys_recvmsg)( tid, ARG2_0, ARG2_1 );
sewardja8d8e232005-06-07 20:04:56 +00001616 break;
1617
1618 default:
1619 VG_(message)(Vg_DebugMsg,"FATAL: unhandled socketcall 0x%x",ARG1);
1620 VG_(core_panic)("... bye!\n");
1621 break; /*NOTREACHED*/
1622 }
1623# undef ARG2_0
1624# undef ARG2_1
1625# undef ARG2_2
1626# undef ARG2_3
1627# undef ARG2_4
1628# undef ARG2_5
1629}
1630
sewardj696c5512005-06-08 23:38:32 +00001631/* Convert from non-RT to RT sigset_t's */
1632static
1633void convert_sigset_to_rt(const vki_old_sigset_t *oldset, vki_sigset_t *set)
1634{
1635 VG_(sigemptyset)(set);
1636 set->sig[0] = *oldset;
1637}
1638PRE(sys_sigaction)
1639{
1640 struct vki_sigaction new, old;
1641 struct vki_sigaction *newp, *oldp;
1642
1643 PRINT("sys_sigaction ( %d, %p, %p )", ARG1,ARG2,ARG3);
1644 PRE_REG_READ3(int, "sigaction",
1645 int, signum, const struct old_sigaction *, act,
1646 struct old_sigaction *, oldact);
1647
1648 newp = oldp = NULL;
1649
tomd9cac2f2005-08-07 15:16:59 +00001650 if (ARG2 != 0) {
1651 struct vki_old_sigaction *sa = (struct vki_old_sigaction *)ARG2;
tom9b52a342005-08-08 16:50:16 +00001652 PRE_MEM_READ( "sigaction(act->sa_handler)", (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler));
1653 PRE_MEM_READ( "sigaction(act->sa_mask)", (Addr)&sa->sa_mask, sizeof(sa->sa_mask));
1654 PRE_MEM_READ( "sigaction(act->sa_flags)", (Addr)&sa->sa_flags, sizeof(sa->sa_flags));
sewardj45f4e7c2005-09-27 19:20:21 +00001655 if (ML_(safe_to_deref)(sa,sizeof(sa))
1656 && (sa->sa_flags & VKI_SA_RESTORER))
tom9b52a342005-08-08 16:50:16 +00001657 PRE_MEM_READ( "sigaction(act->sa_restorer)", (Addr)&sa->sa_restorer, sizeof(sa->sa_restorer));
tomd9cac2f2005-08-07 15:16:59 +00001658 }
sewardj696c5512005-06-08 23:38:32 +00001659
1660 if (ARG3 != 0) {
1661 PRE_MEM_WRITE( "sigaction(oldact)", ARG3, sizeof(struct vki_old_sigaction));
1662 oldp = &old;
1663 }
1664
1665 //jrs 20050207: what?! how can this make any sense?
1666 //if (VG_(is_kerror)(SYSRES))
1667 // return;
1668
1669 if (ARG2 != 0) {
1670 struct vki_old_sigaction *oldnew = (struct vki_old_sigaction *)ARG2;
1671
1672 new.ksa_handler = oldnew->ksa_handler;
1673 new.sa_flags = oldnew->sa_flags;
1674 new.sa_restorer = oldnew->sa_restorer;
1675 convert_sigset_to_rt(&oldnew->sa_mask, &new.sa_mask);
1676 newp = &new;
1677 }
1678
1679 SET_STATUS_from_SysRes( VG_(do_sys_sigaction)(ARG1, newp, oldp) );
1680
1681 if (ARG3 != 0 && SUCCESS && RES == 0) {
1682 struct vki_old_sigaction *oldold = (struct vki_old_sigaction *)ARG3;
1683
1684 oldold->ksa_handler = oldp->ksa_handler;
1685 oldold->sa_flags = oldp->sa_flags;
1686 oldold->sa_restorer = oldp->sa_restorer;
1687 oldold->sa_mask = oldp->sa_mask.sig[0];
1688 }
1689}
1690
1691POST(sys_sigaction)
1692{
1693 vg_assert(SUCCESS);
1694 if (RES == 0 && ARG3 != 0)
1695 POST_MEM_WRITE( ARG3, sizeof(struct vki_old_sigaction));
1696}
1697
tom313639f2006-04-03 16:38:33 +00001698PRE(sys_sigsuspend)
1699{
1700 /* The C library interface to sigsuspend just takes a pointer to
1701 a signal mask but this system call has three arguments - the first
1702 two don't appear to be used by the kernel and are always passed as
1703 zero by glibc and the third is the first word of the signal mask
1704 so only 32 signals are supported.
1705
1706 In fact glibc normally uses rt_sigsuspend if it is available as
1707 that takes a pointer to the signal mask so supports more signals.
1708 */
1709 *flags |= SfMayBlock;
1710 PRINT("sys_sigsuspend ( %d, %d, %d )", ARG1,ARG2,ARG3 );
1711 PRE_REG_READ3(int, "sigsuspend",
1712 int, history0, int, history1,
1713 vki_old_sigset_t, mask);
1714}
1715
tomc1369aa2006-02-11 16:26:46 +00001716PRE(sys_vm86old)
1717{
1718 PRINT("sys_vm86old ( %p )", ARG1);
1719 PRE_REG_READ1(int, "vm86old", struct vm86_struct *, info);
1720 PRE_MEM_WRITE( "vm86old(info)", ARG1, sizeof(struct vki_vm86_struct));
1721}
1722
1723POST(sys_vm86old)
1724{
1725 POST_MEM_WRITE( ARG1, sizeof(struct vki_vm86_struct));
1726}
1727
1728PRE(sys_vm86)
1729{
1730 PRINT("sys_vm86 ( %d, %p )", ARG1,ARG2);
1731 PRE_REG_READ2(int, "vm86", unsigned long, fn, struct vm86plus_struct *, v86);
1732 if (ARG1 == VKI_VM86_ENTER || ARG1 == VKI_VM86_ENTER_NO_BYPASS)
1733 PRE_MEM_WRITE( "vm86(v86)", ARG2, sizeof(struct vki_vm86plus_struct));
1734}
1735
1736POST(sys_vm86)
1737{
1738 if (ARG1 == VKI_VM86_ENTER || ARG1 == VKI_VM86_ENTER_NO_BYPASS)
1739 POST_MEM_WRITE( ARG2, sizeof(struct vki_vm86plus_struct));
1740}
1741
sewardjce5a5662005-10-06 03:19:49 +00001742
1743/* ---------------------------------------------------------------
1744 PRE/POST wrappers for x86/Linux-variant specific syscalls
1745 ------------------------------------------------------------ */
1746
1747PRE(sys_syscall223)
1748{
1749 Int err;
1750
1751 /* 223 is used by sys_bproc. If we're not on a declared bproc
1752 variant, fail in the usual way. */
1753
1754 if (!VG_(strstr)(VG_(clo_kernel_variant), "bproc")) {
1755 PRINT("non-existent syscall! (syscall 223)");
1756 PRE_REG_READ0(long, "ni_syscall(223)");
1757 SET_STATUS_Failure( VKI_ENOSYS );
1758 return;
1759 }
1760
1761 err = ML_(linux_variant_PRE_sys_bproc)( ARG1, ARG2, ARG3,
1762 ARG4, ARG5, ARG6 );
1763 if (err) {
1764 SET_STATUS_Failure( err );
1765 return;
1766 }
1767 /* Let it go through. */
1768 *flags |= SfMayBlock; /* who knows? play safe. */
1769}
1770
1771POST(sys_syscall223)
1772{
1773 ML_(linux_variant_POST_sys_bproc)( ARG1, ARG2, ARG3,
1774 ARG4, ARG5, ARG6 );
1775}
1776
sewardj696c5512005-06-08 23:38:32 +00001777#undef PRE
1778#undef POST
1779
nethercote8ff888f2004-11-17 17:11:45 +00001780
1781/* ---------------------------------------------------------------------
1782 The x86/Linux syscall table
1783 ------------------------------------------------------------------ */
1784
sewardje7aa4ae2005-06-09 12:43:42 +00001785/* Add an x86-linux specific wrapper to a syscall table. */
sewardja8d8e232005-06-07 20:04:56 +00001786#define PLAX_(sysno, name) WRAPPER_ENTRY_X_(x86_linux, sysno, name)
1787#define PLAXY(sysno, name) WRAPPER_ENTRY_XY(x86_linux, sysno, name)
1788
nethercote8ff888f2004-11-17 17:11:45 +00001789
nethercote3d5e9102004-11-17 18:22:38 +00001790// This table maps from __NR_xxx syscall numbers (from
1791// linux/include/asm-i386/unistd.h) to the appropriate PRE/POST sys_foo()
1792// wrappers on x86 (as per sys_call_table in linux/arch/i386/kernel/entry.S).
1793//
1794// For those syscalls not handled by Valgrind, the annotation indicate its
1795// arch/OS combination, eg. */* (generic), */Linux (Linux only), ?/?
1796// (unknown).
1797
njnaf839f52005-06-23 03:27:57 +00001798const SyscallTableEntry ML_(syscall_table)[] = {
sewardja8d8e232005-06-07 20:04:56 +00001799//zz // (restart_syscall) // 0
nethercote8ff888f2004-11-17 17:11:45 +00001800 GENX_(__NR_exit, sys_exit), // 1
sewardjb5f6f512005-03-10 23:59:00 +00001801 GENX_(__NR_fork, sys_fork), // 2
nethercote8ff888f2004-11-17 17:11:45 +00001802 GENXY(__NR_read, sys_read), // 3
1803 GENX_(__NR_write, sys_write), // 4
1804
1805 GENXY(__NR_open, sys_open), // 5
1806 GENXY(__NR_close, sys_close), // 6
1807 GENXY(__NR_waitpid, sys_waitpid), // 7
1808 GENXY(__NR_creat, sys_creat), // 8
1809 GENX_(__NR_link, sys_link), // 9
1810
1811 GENX_(__NR_unlink, sys_unlink), // 10
nethercote3d5e9102004-11-17 18:22:38 +00001812 GENX_(__NR_execve, sys_execve), // 11
nethercote8ff888f2004-11-17 17:11:45 +00001813 GENX_(__NR_chdir, sys_chdir), // 12
1814 GENXY(__NR_time, sys_time), // 13
1815 GENX_(__NR_mknod, sys_mknod), // 14
1816
1817 GENX_(__NR_chmod, sys_chmod), // 15
njnefc957c2005-08-26 04:36:10 +00001818//zz LINX_(__NR_lchown, sys_lchown16), // 16
nethercote3d5e9102004-11-17 18:22:38 +00001819 GENX_(__NR_break, sys_ni_syscall), // 17
sewardja8d8e232005-06-07 20:04:56 +00001820//zz // (__NR_oldstat, sys_stat), // 18 (obsolete)
njncd405ea2005-08-31 02:44:31 +00001821 LINX_(__NR_lseek, sys_lseek), // 19
nethercote8ff888f2004-11-17 17:11:45 +00001822
1823 GENX_(__NR_getpid, sys_getpid), // 20
1824 LINX_(__NR_mount, sys_mount), // 21
1825 LINX_(__NR_umount, sys_oldumount), // 22
njna3b67b72005-08-26 04:27:54 +00001826 LINX_(__NR_setuid, sys_setuid16), // 23 ## P
1827 LINX_(__NR_getuid, sys_getuid16), // 24 ## P
sewardja8d8e232005-06-07 20:04:56 +00001828//zz
1829//zz // (__NR_stime, sys_stime), // 25 * (SVr4,SVID,X/OPEN)
sewardj8c257322005-06-08 01:01:48 +00001830 PLAXY(__NR_ptrace, sys_ptrace), // 26
nethercote3d5e9102004-11-17 18:22:38 +00001831 GENX_(__NR_alarm, sys_alarm), // 27
sewardja8d8e232005-06-07 20:04:56 +00001832//zz // (__NR_oldfstat, sys_fstat), // 28 * L -- obsolete
nethercote3d5e9102004-11-17 18:22:38 +00001833 GENX_(__NR_pause, sys_pause), // 29
sewardj8c9ea4e2005-06-08 10:46:56 +00001834
njncd405ea2005-08-31 02:44:31 +00001835 LINX_(__NR_utime, sys_utime), // 30
nethercote3d5e9102004-11-17 18:22:38 +00001836 GENX_(__NR_stty, sys_ni_syscall), // 31
1837 GENX_(__NR_gtty, sys_ni_syscall), // 32
1838 GENX_(__NR_access, sys_access), // 33
sewardj8c9ea4e2005-06-08 10:46:56 +00001839 GENX_(__NR_nice, sys_nice), // 34
1840
nethercote3d5e9102004-11-17 18:22:38 +00001841 GENX_(__NR_ftime, sys_ni_syscall), // 35
sewardj8c9ea4e2005-06-08 10:46:56 +00001842 GENX_(__NR_sync, sys_sync), // 36
njn03f1e582005-03-26 20:08:06 +00001843 GENX_(__NR_kill, sys_kill), // 37
nethercote8ff888f2004-11-17 17:11:45 +00001844 GENX_(__NR_rename, sys_rename), // 38
1845 GENX_(__NR_mkdir, sys_mkdir), // 39
sewardj78b50e42005-06-08 01:47:28 +00001846
1847 GENX_(__NR_rmdir, sys_rmdir), // 40
nethercote8ff888f2004-11-17 17:11:45 +00001848 GENXY(__NR_dup, sys_dup), // 41
njncd405ea2005-08-31 02:44:31 +00001849 LINXY(__NR_pipe, sys_pipe), // 42
sewardj78b50e42005-06-08 01:47:28 +00001850 GENXY(__NR_times, sys_times), // 43
nethercote3d5e9102004-11-17 18:22:38 +00001851 GENX_(__NR_prof, sys_ni_syscall), // 44
sewardja8d8e232005-06-07 20:04:56 +00001852//zz
nethercote3d5e9102004-11-17 18:22:38 +00001853 GENX_(__NR_brk, sys_brk), // 45
njna3b67b72005-08-26 04:27:54 +00001854 LINX_(__NR_setgid, sys_setgid16), // 46
1855 LINX_(__NR_getgid, sys_getgid16), // 47
sewardja8d8e232005-06-07 20:04:56 +00001856//zz // (__NR_signal, sys_signal), // 48 */* (ANSI C)
njna3b67b72005-08-26 04:27:54 +00001857 LINX_(__NR_geteuid, sys_geteuid16), // 49
sewardj696c5512005-06-08 23:38:32 +00001858
njna3b67b72005-08-26 04:27:54 +00001859 LINX_(__NR_getegid, sys_getegid16), // 50
sewardj696c5512005-06-08 23:38:32 +00001860 GENX_(__NR_acct, sys_acct), // 51
1861 LINX_(__NR_umount2, sys_umount), // 52
nethercote3d5e9102004-11-17 18:22:38 +00001862 GENX_(__NR_lock, sys_ni_syscall), // 53
1863 GENXY(__NR_ioctl, sys_ioctl), // 54
sewardj696c5512005-06-08 23:38:32 +00001864
1865 GENXY(__NR_fcntl, sys_fcntl), // 55
nethercote3d5e9102004-11-17 18:22:38 +00001866 GENX_(__NR_mpx, sys_ni_syscall), // 56
sewardj696c5512005-06-08 23:38:32 +00001867 GENX_(__NR_setpgid, sys_setpgid), // 57
nethercote3d5e9102004-11-17 18:22:38 +00001868 GENX_(__NR_ulimit, sys_ni_syscall), // 58
sewardja8d8e232005-06-07 20:04:56 +00001869//zz // (__NR_oldolduname, sys_olduname), // 59 Linux -- obsolete
1870//zz
sewardj78b50e42005-06-08 01:47:28 +00001871 GENX_(__NR_umask, sys_umask), // 60
sewardj696c5512005-06-08 23:38:32 +00001872 GENX_(__NR_chroot, sys_chroot), // 61
sewardja8d8e232005-06-07 20:04:56 +00001873//zz // (__NR_ustat, sys_ustat) // 62 SVr4 -- deprecated
nethercote8ff888f2004-11-17 17:11:45 +00001874 GENXY(__NR_dup2, sys_dup2), // 63
sewardj1d887112005-05-30 21:44:08 +00001875 GENX_(__NR_getppid, sys_getppid), // 64
sewardj78b50e42005-06-08 01:47:28 +00001876
1877 GENX_(__NR_getpgrp, sys_getpgrp), // 65
sewardj696c5512005-06-08 23:38:32 +00001878 GENX_(__NR_setsid, sys_setsid), // 66
1879 PLAXY(__NR_sigaction, sys_sigaction), // 67
sewardja8d8e232005-06-07 20:04:56 +00001880//zz // (__NR_sgetmask, sys_sgetmask), // 68 */* (ANSI C)
1881//zz // (__NR_ssetmask, sys_ssetmask), // 69 */* (ANSI C)
1882//zz
njna3b67b72005-08-26 04:27:54 +00001883 LINX_(__NR_setreuid, sys_setreuid16), // 70
1884 LINX_(__NR_setregid, sys_setregid16), // 71
tom313639f2006-04-03 16:38:33 +00001885 PLAX_(__NR_sigsuspend, sys_sigsuspend), // 72
njncd405ea2005-08-31 02:44:31 +00001886 LINXY(__NR_sigpending, sys_sigpending), // 73
sewardja8d8e232005-06-07 20:04:56 +00001887//zz // (__NR_sethostname, sys_sethostname), // 74 */*
1888//zz
nethercote3d5e9102004-11-17 18:22:38 +00001889 GENX_(__NR_setrlimit, sys_setrlimit), // 75
sewardj696c5512005-06-08 23:38:32 +00001890 GENXY(__NR_getrlimit, sys_old_getrlimit), // 76
1891 GENXY(__NR_getrusage, sys_getrusage), // 77
nethercote3d5e9102004-11-17 18:22:38 +00001892 GENXY(__NR_gettimeofday, sys_gettimeofday), // 78
sewardj696c5512005-06-08 23:38:32 +00001893 GENX_(__NR_settimeofday, sys_settimeofday), // 79
1894
njna3b67b72005-08-26 04:27:54 +00001895 LINXY(__NR_getgroups, sys_getgroups16), // 80
1896 LINX_(__NR_setgroups, sys_setgroups16), // 81
sewardj696c5512005-06-08 23:38:32 +00001897 PLAX_(__NR_select, old_select), // 82
sewardj78b50e42005-06-08 01:47:28 +00001898 GENX_(__NR_symlink, sys_symlink), // 83
sewardja8d8e232005-06-07 20:04:56 +00001899//zz // (__NR_oldlstat, sys_lstat), // 84 -- obsolete
1900//zz
rjwalsh17d85302004-11-18 22:56:09 +00001901 GENX_(__NR_readlink, sys_readlink), // 85
sewardja8d8e232005-06-07 20:04:56 +00001902//zz // (__NR_uselib, sys_uselib), // 86 */Linux
1903//zz // (__NR_swapon, sys_swapon), // 87 */Linux
1904//zz // (__NR_reboot, sys_reboot), // 88 */Linux
1905//zz // (__NR_readdir, old_readdir), // 89 -- superseded
1906//zz
1907 PLAX_(__NR_mmap, old_mmap), // 90
nethercote8ff888f2004-11-17 17:11:45 +00001908 GENXY(__NR_munmap, sys_munmap), // 91
sewardj696c5512005-06-08 23:38:32 +00001909 GENX_(__NR_truncate, sys_truncate), // 92
sewardj8c257322005-06-08 01:01:48 +00001910 GENX_(__NR_ftruncate, sys_ftruncate), // 93
sewardj696c5512005-06-08 23:38:32 +00001911 GENX_(__NR_fchmod, sys_fchmod), // 94
1912
njnefc957c2005-08-26 04:36:10 +00001913 LINX_(__NR_fchown, sys_fchown16), // 95
sewardj696c5512005-06-08 23:38:32 +00001914 GENX_(__NR_getpriority, sys_getpriority), // 96
1915 GENX_(__NR_setpriority, sys_setpriority), // 97
nethercote3d5e9102004-11-17 18:22:38 +00001916 GENX_(__NR_profil, sys_ni_syscall), // 98
sewardj696c5512005-06-08 23:38:32 +00001917 GENXY(__NR_statfs, sys_statfs), // 99
1918
1919 GENXY(__NR_fstatfs, sys_fstatfs), // 100
1920 LINX_(__NR_ioperm, sys_ioperm), // 101
sewardja8d8e232005-06-07 20:04:56 +00001921 PLAXY(__NR_socketcall, sys_socketcall), // 102 x86/Linux-only
sewardj696c5512005-06-08 23:38:32 +00001922 LINXY(__NR_syslog, sys_syslog), // 103
1923 GENXY(__NR_setitimer, sys_setitimer), // 104
1924
1925 GENXY(__NR_getitimer, sys_getitimer), // 105
1926 GENXY(__NR_stat, sys_newstat), // 106
1927 GENXY(__NR_lstat, sys_newlstat), // 107
1928 GENXY(__NR_fstat, sys_newfstat), // 108
sewardja8d8e232005-06-07 20:04:56 +00001929//zz // (__NR_olduname, sys_uname), // 109 -- obsolete
1930//zz
sewardj696c5512005-06-08 23:38:32 +00001931 GENX_(__NR_iopl, sys_iopl), // 110
1932 LINX_(__NR_vhangup, sys_vhangup), // 111
nethercote3d5e9102004-11-17 18:22:38 +00001933 GENX_(__NR_idle, sys_ni_syscall), // 112
tomc1369aa2006-02-11 16:26:46 +00001934 PLAXY(__NR_vm86old, sys_vm86old), // 113 x86/Linux-only
nethercote3d5e9102004-11-17 18:22:38 +00001935 GENXY(__NR_wait4, sys_wait4), // 114
sewardja8d8e232005-06-07 20:04:56 +00001936//zz
1937//zz // (__NR_swapoff, sys_swapoff), // 115 */Linux
sewardj696c5512005-06-08 23:38:32 +00001938 LINXY(__NR_sysinfo, sys_sysinfo), // 116
njnc6168192004-11-29 13:54:10 +00001939 PLAXY(__NR_ipc, sys_ipc), // 117
sewardj78b50e42005-06-08 01:47:28 +00001940 GENX_(__NR_fsync, sys_fsync), // 118
sewardjb5f6f512005-03-10 23:59:00 +00001941 PLAX_(__NR_sigreturn, sys_sigreturn), // 119 ?/Linux
nethercote8ff888f2004-11-17 17:11:45 +00001942
nethercote3d5e9102004-11-17 18:22:38 +00001943 PLAX_(__NR_clone, sys_clone), // 120
sewardja8d8e232005-06-07 20:04:56 +00001944//zz // (__NR_setdomainname, sys_setdomainname), // 121 */*(?)
nethercote3d5e9102004-11-17 18:22:38 +00001945 GENXY(__NR_uname, sys_newuname), // 122
1946 PLAX_(__NR_modify_ldt, sys_modify_ldt), // 123
sewardja8d8e232005-06-07 20:04:56 +00001947//zz LINXY(__NR_adjtimex, sys_adjtimex), // 124
1948//zz
nethercote3d5e9102004-11-17 18:22:38 +00001949 GENXY(__NR_mprotect, sys_mprotect), // 125
njncd405ea2005-08-31 02:44:31 +00001950 LINXY(__NR_sigprocmask, sys_sigprocmask), // 126
sewardja8d8e232005-06-07 20:04:56 +00001951//zz // Nb: create_module() was removed 2.4-->2.6
nethercote3d5e9102004-11-17 18:22:38 +00001952 GENX_(__NR_create_module, sys_ni_syscall), // 127
sewardj696c5512005-06-08 23:38:32 +00001953 GENX_(__NR_init_module, sys_init_module), // 128
sewardja8d8e232005-06-07 20:04:56 +00001954//zz // (__NR_delete_module, sys_delete_module), // 129 (*/Linux)?
1955//zz
1956//zz // Nb: get_kernel_syms() was removed 2.4-->2.6
nethercote3d5e9102004-11-17 18:22:38 +00001957 GENX_(__NR_get_kernel_syms, sys_ni_syscall), // 130
njncd405ea2005-08-31 02:44:31 +00001958 LINX_(__NR_quotactl, sys_quotactl), // 131
sewardj696c5512005-06-08 23:38:32 +00001959 GENX_(__NR_getpgid, sys_getpgid), // 132
1960 GENX_(__NR_fchdir, sys_fchdir), // 133
sewardja8d8e232005-06-07 20:04:56 +00001961//zz // (__NR_bdflush, sys_bdflush), // 134 */Linux
1962//zz
1963//zz // (__NR_sysfs, sys_sysfs), // 135 SVr4
sewardj696c5512005-06-08 23:38:32 +00001964 LINX_(__NR_personality, sys_personality), // 136
nethercote3d5e9102004-11-17 18:22:38 +00001965 GENX_(__NR_afs_syscall, sys_ni_syscall), // 137
sewardj696c5512005-06-08 23:38:32 +00001966 LINX_(__NR_setfsuid, sys_setfsuid16), // 138
1967 LINX_(__NR_setfsgid, sys_setfsgid16), // 139
1968
nethercote8ff888f2004-11-17 17:11:45 +00001969 LINXY(__NR__llseek, sys_llseek), // 140
sewardj78b50e42005-06-08 01:47:28 +00001970 GENXY(__NR_getdents, sys_getdents), // 141
nethercote3d5e9102004-11-17 18:22:38 +00001971 GENX_(__NR__newselect, sys_select), // 142
sewardj696c5512005-06-08 23:38:32 +00001972 GENX_(__NR_flock, sys_flock), // 143
1973 GENX_(__NR_msync, sys_msync), // 144
1974
nethercote3d5e9102004-11-17 18:22:38 +00001975 GENXY(__NR_readv, sys_readv), // 145
1976 GENX_(__NR_writev, sys_writev), // 146
sewardj696c5512005-06-08 23:38:32 +00001977 GENX_(__NR_getsid, sys_getsid), // 147
1978 GENX_(__NR_fdatasync, sys_fdatasync), // 148
nethercote8ff888f2004-11-17 17:11:45 +00001979 LINXY(__NR__sysctl, sys_sysctl), // 149
sewardj696c5512005-06-08 23:38:32 +00001980
1981 GENX_(__NR_mlock, sys_mlock), // 150
1982 GENX_(__NR_munlock, sys_munlock), // 151
1983 GENX_(__NR_mlockall, sys_mlockall), // 152
njncd405ea2005-08-31 02:44:31 +00001984 LINX_(__NR_munlockall, sys_munlockall), // 153
njnb2480c92005-08-30 02:17:23 +00001985 LINXY(__NR_sched_setparam, sys_sched_setparam), // 154
sewardje6d5e722005-06-10 10:27:55 +00001986
njnb2480c92005-08-30 02:17:23 +00001987 LINXY(__NR_sched_getparam, sys_sched_getparam), // 155
1988 LINX_(__NR_sched_setscheduler, sys_sched_setscheduler), // 156
1989 LINX_(__NR_sched_getscheduler, sys_sched_getscheduler), // 157
1990 LINX_(__NR_sched_yield, sys_sched_yield), // 158
1991 LINX_(__NR_sched_get_priority_max, sys_sched_get_priority_max),// 159
sewardj78b50e42005-06-08 01:47:28 +00001992
njnb2480c92005-08-30 02:17:23 +00001993 LINX_(__NR_sched_get_priority_min, sys_sched_get_priority_min),// 160
1994//zz //LINX?(__NR_sched_rr_get_interval, sys_sched_rr_get_interval), // 161 */*
nethercote8ff888f2004-11-17 17:11:45 +00001995 GENXY(__NR_nanosleep, sys_nanosleep), // 162
1996 GENX_(__NR_mremap, sys_mremap), // 163
sewardje6d5e722005-06-10 10:27:55 +00001997 LINX_(__NR_setresuid, sys_setresuid16), // 164
1998
1999 LINXY(__NR_getresuid, sys_getresuid16), // 165
tomc1369aa2006-02-11 16:26:46 +00002000 PLAXY(__NR_vm86, sys_vm86), // 166 x86/Linux-only
nethercote3d5e9102004-11-17 18:22:38 +00002001 GENX_(__NR_query_module, sys_ni_syscall), // 167
2002 GENXY(__NR_poll, sys_poll), // 168
sewardja8d8e232005-06-07 20:04:56 +00002003//zz // (__NR_nfsservctl, sys_nfsservctl), // 169 */Linux
2004//zz
sewardje6d5e722005-06-10 10:27:55 +00002005 LINX_(__NR_setresgid, sys_setresgid16), // 170
2006 LINXY(__NR_getresgid, sys_getresgid16), // 171
2007 LINX_(__NR_prctl, sys_prctl), // 172
sewardjd571aff2005-03-15 14:47:30 +00002008 PLAX_(__NR_rt_sigreturn, sys_rt_sigreturn), // 173 x86/Linux only?
njncd405ea2005-08-31 02:44:31 +00002009 LINXY(__NR_rt_sigaction, sys_rt_sigaction), // 174
nethercote8ff888f2004-11-17 17:11:45 +00002010
njncd405ea2005-08-31 02:44:31 +00002011 LINXY(__NR_rt_sigprocmask, sys_rt_sigprocmask), // 175
2012 LINXY(__NR_rt_sigpending, sys_rt_sigpending), // 176
2013 LINXY(__NR_rt_sigtimedwait, sys_rt_sigtimedwait),// 177
2014 LINXY(__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo),// 178
2015 LINX_(__NR_rt_sigsuspend, sys_rt_sigsuspend), // 179
sewardje6d5e722005-06-10 10:27:55 +00002016
2017 GENXY(__NR_pread64, sys_pread64), // 180
2018 GENX_(__NR_pwrite64, sys_pwrite64), // 181
njnefc957c2005-08-26 04:36:10 +00002019 LINX_(__NR_chown, sys_chown16), // 182
nethercote3d5e9102004-11-17 18:22:38 +00002020 GENXY(__NR_getcwd, sys_getcwd), // 183
njn9fe7b122005-08-26 04:03:04 +00002021 LINXY(__NR_capget, sys_capget), // 184
sewardje6d5e722005-06-10 10:27:55 +00002022
njn9fe7b122005-08-26 04:03:04 +00002023 LINX_(__NR_capset, sys_capset), // 185
nethercote3d5e9102004-11-17 18:22:38 +00002024 GENXY(__NR_sigaltstack, sys_sigaltstack), // 186
sewardje6d5e722005-06-10 10:27:55 +00002025 LINXY(__NR_sendfile, sys_sendfile), // 187
2026 GENXY(__NR_getpmsg, sys_getpmsg), // 188
2027 GENX_(__NR_putpmsg, sys_putpmsg), // 189
nethercote8ff888f2004-11-17 17:11:45 +00002028
sewardjc93d7b62005-03-12 20:45:56 +00002029 // Nb: we treat vfork as fork
2030 GENX_(__NR_vfork, sys_fork), // 190
nethercote3d5e9102004-11-17 18:22:38 +00002031 GENXY(__NR_ugetrlimit, sys_getrlimit), // 191
tom9548a162005-09-30 08:07:53 +00002032 PLAX_(__NR_mmap2, sys_mmap2), // 192
sewardje6d5e722005-06-10 10:27:55 +00002033 GENX_(__NR_truncate64, sys_truncate64), // 193
2034 GENX_(__NR_ftruncate64, sys_ftruncate64), // 194
2035
sewardja8d8e232005-06-07 20:04:56 +00002036 PLAXY(__NR_stat64, sys_stat64), // 195
2037 PLAXY(__NR_lstat64, sys_lstat64), // 196
2038 PLAXY(__NR_fstat64, sys_fstat64), // 197
sewardje6d5e722005-06-10 10:27:55 +00002039 GENX_(__NR_lchown32, sys_lchown), // 198
nethercote8ff888f2004-11-17 17:11:45 +00002040 GENX_(__NR_getuid32, sys_getuid), // 199
sewardj78b50e42005-06-08 01:47:28 +00002041
2042 GENX_(__NR_getgid32, sys_getgid), // 200
nethercote8ff888f2004-11-17 17:11:45 +00002043 GENX_(__NR_geteuid32, sys_geteuid), // 201
sewardj78b50e42005-06-08 01:47:28 +00002044 GENX_(__NR_getegid32, sys_getegid), // 202
sewardje6d5e722005-06-10 10:27:55 +00002045 GENX_(__NR_setreuid32, sys_setreuid), // 203
2046 GENX_(__NR_setregid32, sys_setregid), // 204
sewardj78b50e42005-06-08 01:47:28 +00002047
2048 GENXY(__NR_getgroups32, sys_getgroups), // 205
sewardje6d5e722005-06-10 10:27:55 +00002049 GENX_(__NR_setgroups32, sys_setgroups), // 206
2050 GENX_(__NR_fchown32, sys_fchown), // 207
2051 LINX_(__NR_setresuid32, sys_setresuid), // 208
sewardj78b50e42005-06-08 01:47:28 +00002052 LINXY(__NR_getresuid32, sys_getresuid), // 209
2053
sewardje6d5e722005-06-10 10:27:55 +00002054 LINX_(__NR_setresgid32, sys_setresgid), // 210
sewardj78b50e42005-06-08 01:47:28 +00002055 LINXY(__NR_getresgid32, sys_getresgid), // 211
sewardje6d5e722005-06-10 10:27:55 +00002056 GENX_(__NR_chown32, sys_chown), // 212
2057 GENX_(__NR_setuid32, sys_setuid), // 213
2058 GENX_(__NR_setgid32, sys_setgid), // 214
2059
2060 LINX_(__NR_setfsuid32, sys_setfsuid), // 215
2061 LINX_(__NR_setfsgid32, sys_setfsgid), // 216
sewardja8d8e232005-06-07 20:04:56 +00002062//zz // (__NR_pivot_root, sys_pivot_root), // 217 */Linux
sewardje6d5e722005-06-10 10:27:55 +00002063 GENXY(__NR_mincore, sys_mincore), // 218
nethercote3d5e9102004-11-17 18:22:38 +00002064 GENX_(__NR_madvise, sys_madvise), // 219
nethercote8ff888f2004-11-17 17:11:45 +00002065
nethercote3d5e9102004-11-17 18:22:38 +00002066 GENXY(__NR_getdents64, sys_getdents64), // 220
2067 GENXY(__NR_fcntl64, sys_fcntl64), // 221
2068 GENX_(222, sys_ni_syscall), // 222
sewardjce5a5662005-10-06 03:19:49 +00002069 PLAXY(223, sys_syscall223), // 223 // sys_bproc?
sewardj8c257322005-06-08 01:01:48 +00002070 LINX_(__NR_gettid, sys_gettid), // 224
2071
sewardja8d8e232005-06-07 20:04:56 +00002072//zz // (__NR_readahead, sys_readahead), // 225 */(Linux?)
njn65ccc502005-08-30 01:53:54 +00002073 LINX_(__NR_setxattr, sys_setxattr), // 226
2074 LINX_(__NR_lsetxattr, sys_lsetxattr), // 227
2075 LINX_(__NR_fsetxattr, sys_fsetxattr), // 228
2076 LINXY(__NR_getxattr, sys_getxattr), // 229
sewardje6d5e722005-06-10 10:27:55 +00002077
njn65ccc502005-08-30 01:53:54 +00002078 LINXY(__NR_lgetxattr, sys_lgetxattr), // 230
2079 LINXY(__NR_fgetxattr, sys_fgetxattr), // 231
2080 LINXY(__NR_listxattr, sys_listxattr), // 232
2081 LINXY(__NR_llistxattr, sys_llistxattr), // 233
2082 LINXY(__NR_flistxattr, sys_flistxattr), // 234
sewardje6d5e722005-06-10 10:27:55 +00002083
njn65ccc502005-08-30 01:53:54 +00002084 LINX_(__NR_removexattr, sys_removexattr), // 235
2085 LINX_(__NR_lremovexattr, sys_lremovexattr), // 236
2086 LINX_(__NR_fremovexattr, sys_fremovexattr), // 237
tomc8cfca62006-02-15 10:34:50 +00002087 LINXY(__NR_tkill, sys_tkill), // 238 */Linux
sewardje6d5e722005-06-10 10:27:55 +00002088 LINXY(__NR_sendfile64, sys_sendfile64), // 239
2089
sewardjbc22cf72005-06-08 00:02:49 +00002090 LINXY(__NR_futex, sys_futex), // 240
njnb2480c92005-08-30 02:17:23 +00002091 LINX_(__NR_sched_setaffinity, sys_sched_setaffinity), // 241
2092 LINXY(__NR_sched_getaffinity, sys_sched_getaffinity), // 242
sewardjbc22cf72005-06-08 00:02:49 +00002093 PLAX_(__NR_set_thread_area, sys_set_thread_area), // 243
sewardje6d5e722005-06-10 10:27:55 +00002094 PLAX_(__NR_get_thread_area, sys_get_thread_area), // 244
2095
sewardj45f4e7c2005-09-27 19:20:21 +00002096 LINXY(__NR_io_setup, sys_io_setup), // 245
sewardje6d5e722005-06-10 10:27:55 +00002097 LINX_(__NR_io_destroy, sys_io_destroy), // 246
2098 LINXY(__NR_io_getevents, sys_io_getevents), // 247
2099 LINX_(__NR_io_submit, sys_io_submit), // 248
2100 LINXY(__NR_io_cancel, sys_io_cancel), // 249
2101
tom72440832005-06-15 10:31:10 +00002102 LINX_(__NR_fadvise64, sys_fadvise64), // 250 */(Linux?)
nethercote3d5e9102004-11-17 18:22:38 +00002103 GENX_(251, sys_ni_syscall), // 251
sewardjb5f6f512005-03-10 23:59:00 +00002104 LINX_(__NR_exit_group, sys_exit_group), // 252
sewardje6d5e722005-06-10 10:27:55 +00002105 GENXY(__NR_lookup_dcookie, sys_lookup_dcookie), // 253
2106 LINXY(__NR_epoll_create, sys_epoll_create), // 254
2107
2108 LINX_(__NR_epoll_ctl, sys_epoll_ctl), // 255
2109 LINXY(__NR_epoll_wait, sys_epoll_wait), // 256
sewardja8d8e232005-06-07 20:04:56 +00002110//zz // (__NR_remap_file_pages, sys_remap_file_pages), // 257 */Linux
sewardjbc22cf72005-06-08 00:02:49 +00002111 LINX_(__NR_set_tid_address, sys_set_tid_address), // 258
njn424c0562005-08-26 03:54:30 +00002112 LINXY(__NR_timer_create, sys_timer_create), // 259
sewardje6d5e722005-06-10 10:27:55 +00002113
njn424c0562005-08-26 03:54:30 +00002114 LINXY(__NR_timer_settime, sys_timer_settime), // (timer_create+1)
2115 LINXY(__NR_timer_gettime, sys_timer_gettime), // (timer_create+2)
2116 LINX_(__NR_timer_getoverrun, sys_timer_getoverrun),//(timer_create+3)
2117 LINX_(__NR_timer_delete, sys_timer_delete), // (timer_create+4)
njn1588bc02005-08-26 03:49:43 +00002118 LINX_(__NR_clock_settime, sys_clock_settime), // (timer_create+5)
sewardje6d5e722005-06-10 10:27:55 +00002119
njn1588bc02005-08-26 03:49:43 +00002120 LINXY(__NR_clock_gettime, sys_clock_gettime), // (timer_create+6)
2121 LINXY(__NR_clock_getres, sys_clock_getres), // (timer_create+7)
2122 LINXY(__NR_clock_nanosleep, sys_clock_nanosleep),// (timer_create+8) */*
sewardje6d5e722005-06-10 10:27:55 +00002123 GENXY(__NR_statfs64, sys_statfs64), // 268
2124 GENXY(__NR_fstatfs64, sys_fstatfs64), // 269
2125
sewardjbc22cf72005-06-08 00:02:49 +00002126 LINX_(__NR_tgkill, sys_tgkill), // 270 */Linux
sewardje6d5e722005-06-10 10:27:55 +00002127 GENX_(__NR_utimes, sys_utimes), // 271
tom72440832005-06-15 10:31:10 +00002128 LINX_(__NR_fadvise64_64, sys_fadvise64_64), // 272 */(Linux?)
nethercote3d5e9102004-11-17 18:22:38 +00002129 GENX_(__NR_vserver, sys_ni_syscall), // 273
tom70a5cb02005-10-20 17:00:23 +00002130 LINX_(__NR_mbind, sys_mbind), // 274 ?/?
2131
tom2af58f22005-07-22 15:04:14 +00002132 LINXY(__NR_get_mempolicy, sys_get_mempolicy), // 275 ?/?
2133 LINX_(__NR_set_mempolicy, sys_set_mempolicy), // 276 ?/?
njn4279a882005-08-26 03:43:28 +00002134 LINXY(__NR_mq_open, sys_mq_open), // 277
2135 LINX_(__NR_mq_unlink, sys_mq_unlink), // (mq_open+1)
2136 LINX_(__NR_mq_timedsend, sys_mq_timedsend), // (mq_open+2)
sewardj8c9ea4e2005-06-08 10:46:56 +00002137
njn4279a882005-08-26 03:43:28 +00002138 LINXY(__NR_mq_timedreceive, sys_mq_timedreceive),// (mq_open+3)
2139 LINX_(__NR_mq_notify, sys_mq_notify), // (mq_open+4)
2140 LINXY(__NR_mq_getsetattr, sys_mq_getsetattr), // (mq_open+5)
nethercote8ff888f2004-11-17 17:11:45 +00002141 GENX_(__NR_sys_kexec_load, sys_ni_syscall), // 283
njncd405ea2005-08-31 02:44:31 +00002142 LINXY(__NR_waitid, sys_waitid), // 284
tom0bcaf2a2005-07-25 15:21:41 +00002143
2144 GENX_(285, sys_ni_syscall), // 285
2145// LINX_(__NR_add_key, sys_add_key), // 286
2146// LINX_(__NR_request_key, sys_request_key), // 287
2147// LINXY(__NR_keyctl, sys_keyctl), // 288
2148// LINX_(__NR_ioprio_set, sys_ioprio_set), // 289
2149
2150// LINX_(__NR_ioprio_get, sys_ioprio_get), // 290
2151 LINX_(__NR_inotify_init, sys_inotify_init), // 291
2152 LINX_(__NR_inotify_add_watch, sys_inotify_add_watch), // 292
2153 LINX_(__NR_inotify_rm_watch, sys_inotify_rm_watch), // 293
tom363ec762006-03-21 10:58:35 +00002154// LINX_(__NR_migrate_pages, sys_migrate_pages), // 294
2155
2156 LINXY(__NR_openat, sys_openat), // 295
2157 LINX_(__NR_mkdirat, sys_mkdirat), // 296
2158 LINX_(__NR_mknodat, sys_mknodat), // 297
2159 LINX_(__NR_fchownat, sys_fchownat), // 298
2160 LINX_(__NR_futimesat, sys_futimesat), // 299
2161
2162 PLAXY(__NR_fstatat64, sys_fstatat64), // 300
2163 LINX_(__NR_unlinkat, sys_unlinkat), // 301
2164 LINX_(__NR_renameat, sys_renameat), // 302
2165 LINX_(__NR_linkat, sys_linkat), // 303
2166 LINX_(__NR_symlinkat, sys_symlinkat), // 304
2167
2168 LINX_(__NR_readlinkat, sys_readlinkat), // 305
2169 LINX_(__NR_fchmodat, sys_fchmodat), // 306
2170 LINX_(__NR_faccessat, sys_faccessat), // 307
2171 LINX_(__NR_pselect6, sys_pselect6), // 308
2172 LINXY(__NR_ppoll, sys_ppoll), // 309
2173
2174// LINX_(__NR_unshare, sys_unshare), // 310
tom05b1f9a2006-05-17 14:24:12 +00002175 LINX_(__NR_set_robust_list, sys_set_robust_list), // 311
2176 LINXY(__NR_get_robust_list, sys_get_robust_list), // 312
nethercote8ff888f2004-11-17 17:11:45 +00002177};
2178
njnaf839f52005-06-23 03:27:57 +00002179const UInt ML_(syscall_table_size) =
2180 sizeof(ML_(syscall_table)) / sizeof(ML_(syscall_table)[0]);
nethercote8ff888f2004-11-17 17:11:45 +00002181
nethercote41c75da2004-10-18 15:34:14 +00002182/*--------------------------------------------------------------------*/
2183/*--- end ---*/
2184/*--------------------------------------------------------------------*/