blob: de5e7371d20c476502411dc65e919f12177bb5c2 [file] [log] [blame]
nethercotefd453532004-11-17 17:21:12 +00001
2/*--------------------------------------------------------------------*/
njnc1b01812005-06-17 22:19:06 +00003/*--- Linux-specific syscalls, etc. syswrap-linux.c ---*/
nethercotefd453532004-11-17 17:21:12 +00004/*--------------------------------------------------------------------*/
5
6/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
nethercotefd453532004-11-17 17:21:12 +00009
sewardje4b0bf02006-06-05 23:21:15 +000010 Copyright (C) 2000-2006 Nicholas Nethercote
njn2bc10122005-05-08 02:10:27 +000011 njn@valgrind.org
nethercotefd453532004-11-17 17:21:12 +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
njnc7561b92005-06-19 01:24:32 +000031#include "pub_core_basics.h"
32#include "pub_core_threadstate.h"
sewardj55f9d1a2005-04-25 11:11:44 +000033#include "pub_core_aspacemgr.h"
sewardj45f4e7c2005-09-27 19:20:21 +000034#include "pub_core_debuginfo.h" // VG_(di_notify_*)
35#include "pub_core_transtab.h" // VG_(discard_translations)
tom363ec762006-03-21 10:58:35 +000036#include "pub_core_clientstate.h"
njn7b85dd52005-06-12 17:26:29 +000037#include "pub_core_debuglog.h"
sewardjbc22cf72005-06-08 00:02:49 +000038#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000039#include "pub_core_libcassert.h"
njneb8896b2005-06-04 20:03:55 +000040#include "pub_core_libcfile.h"
njn36a20fa2005-06-03 03:08:39 +000041#include "pub_core_libcprint.h"
njn7b85dd52005-06-12 17:26:29 +000042#include "pub_core_libcproc.h"
njne1486662005-11-10 02:48:04 +000043#include "pub_core_libcsignal.h"
njnaf1d7df2005-06-11 01:31:52 +000044#include "pub_core_mallocfree.h"
njn43b9a8a2005-05-10 04:37:01 +000045#include "pub_core_tooliface.h"
sewardja8d8e232005-06-07 20:04:56 +000046#include "pub_core_options.h"
njnc7561b92005-06-19 01:24:32 +000047#include "pub_core_scheduler.h"
njncd405ea2005-08-31 02:44:31 +000048#include "pub_core_signals.h"
njn9abd6082005-06-17 21:31:45 +000049#include "pub_core_syscall.h"
njna3afdfb2005-11-09 04:49:28 +000050#include "pub_core_syswrap.h"
sewardja8d8e232005-06-07 20:04:56 +000051
52#include "priv_types_n_macros.h"
njnc1b01812005-06-17 22:19:06 +000053#include "priv_syswrap-generic.h"
54#include "priv_syswrap-linux.h"
sewardja8d8e232005-06-07 20:04:56 +000055
sewardj4eee4762006-10-14 15:51:32 +000056#include "pub_core_vkiscnums.h" /* for the __NR_* constants */
njna3afdfb2005-11-09 04:49:28 +000057
njn7b85dd52005-06-12 17:26:29 +000058// Run a thread from beginning to end and return the thread's
59// scheduler-return-code.
njne1486662005-11-10 02:48:04 +000060static VgSchedReturnCode thread_wrapper(Word /*ThreadId*/ tidW)
njn7b85dd52005-06-12 17:26:29 +000061{
njn7b85dd52005-06-12 17:26:29 +000062 VgSchedReturnCode ret;
63 ThreadId tid = (ThreadId)tidW;
64 ThreadState* tst = VG_(get_ThreadState)(tid);
65
sewardjd98f68d2005-11-09 14:09:14 +000066 VG_(debugLog)(1, "syswrap-linux",
njne1486662005-11-10 02:48:04 +000067 "thread_wrapper(tid=%lld): entry\n",
tom60a4b0b2005-10-12 10:45:27 +000068 (ULong)tidW);
69
njn7b85dd52005-06-12 17:26:29 +000070 vg_assert(tst->status == VgTs_Init);
71
72 /* make sure we get the CPU lock before doing anything significant */
73 VG_(set_running)(tid);
74
75 if (0)
76 VG_(printf)("thread tid %d started: stack = %p\n",
77 tid, &tid);
78
79 VG_TRACK ( post_thread_create, tst->os_state.parent, tid );
80
81 tst->os_state.lwpid = VG_(gettid)();
82 tst->os_state.threadgroup = VG_(getpid)();
83
84 /* Thread created with all signals blocked; scheduler will set the
85 appropriate mask */
86
87 ret = VG_(scheduler)(tid);
88
89 vg_assert(VG_(is_exiting)(tid));
90
91 vg_assert(tst->status == VgTs_Runnable);
92 vg_assert(VG_(is_running_thread)(tid));
93
sewardjd98f68d2005-11-09 14:09:14 +000094 VG_(debugLog)(1, "syswrap-linux",
njne1486662005-11-10 02:48:04 +000095 "thread_wrapper(tid=%lld): exit\n",
njn7b85dd52005-06-12 17:26:29 +000096 (ULong)tidW);
97
98 /* Return to caller, still holding the lock. */
99 return ret;
100}
101
102
nethercotefd453532004-11-17 17:21:12 +0000103/* ---------------------------------------------------------------------
njna3afdfb2005-11-09 04:49:28 +0000104 clone-related stuff
105 ------------------------------------------------------------------ */
106
107/* Run a thread all the way to the end, then do appropriate exit actions
108 (this is the last-one-out-turn-off-the-lights bit). */
njne1486662005-11-10 02:48:04 +0000109static void run_a_thread_NORETURN ( Word tidW )
njna3afdfb2005-11-09 04:49:28 +0000110{
111 ThreadId tid = (ThreadId)tidW;
112 VgSchedReturnCode src;
113 Int c;
114
sewardjd98f68d2005-11-09 14:09:14 +0000115 VG_(debugLog)(1, "syswrap-linux",
njne1486662005-11-10 02:48:04 +0000116 "run_a_thread_NORETURN(tid=%lld): pre-thread_wrapper\n",
117 (ULong)tidW);
njna3afdfb2005-11-09 04:49:28 +0000118
119 /* Run the thread all the way through. */
njne1486662005-11-10 02:48:04 +0000120 src = thread_wrapper(tid);
njna3afdfb2005-11-09 04:49:28 +0000121
sewardjd98f68d2005-11-09 14:09:14 +0000122 VG_(debugLog)(1, "syswrap-linux",
njne1486662005-11-10 02:48:04 +0000123 "run_a_thread_NORETURN(tid=%lld): post-thread_wrapper\n",
124 (ULong)tidW);
njna3afdfb2005-11-09 04:49:28 +0000125
126 c = VG_(count_living_threads)();
127 vg_assert(c >= 1); /* stay sane */
128
129 if (c == 1) {
130
sewardjd98f68d2005-11-09 14:09:14 +0000131 VG_(debugLog)(1, "syswrap-linux",
njna3afdfb2005-11-09 04:49:28 +0000132 "run_a_thread_NORETURN(tid=%lld): "
133 "last one standing\n",
134 (ULong)tidW);
135
136 /* We are the last one standing. Keep hold of the lock and
137 carry on to show final tool results, then exit the entire system.
138 Use the continuation pointer set at startup in m_main. */
139 ( * VG_(address_of_m_main_shutdown_actions_NORETURN) ) (tid, src);
140
141 } else {
142
143 ThreadState *tst;
144
sewardjd98f68d2005-11-09 14:09:14 +0000145 VG_(debugLog)(1, "syswrap-linux",
njna3afdfb2005-11-09 04:49:28 +0000146 "run_a_thread_NORETURN(tid=%lld): "
147 "not last one standing\n",
148 (ULong)tidW);
149
150 /* OK, thread is dead, but others still exist. Just exit. */
151 tst = VG_(get_ThreadState)(tid);
152
153 /* This releases the run lock */
154 VG_(exit_thread)(tid);
155 vg_assert(tst->status == VgTs_Zombie);
156
157 /* We have to use this sequence to terminate the thread to
158 prevent a subtle race. If VG_(exit_thread)() had left the
159 ThreadState as Empty, then it could have been reallocated,
160 reusing the stack while we're doing these last cleanups.
161 Instead, VG_(exit_thread) leaves it as Zombie to prevent
162 reallocation. We need to make sure we don't touch the stack
163 between marking it Empty and exiting. Hence the
164 assembler. */
165#if defined(VGP_x86_linux)
166 asm volatile (
167 "movl %1, %0\n" /* set tst->status = VgTs_Empty */
168 "movl %2, %%eax\n" /* set %eax = __NR_exit */
169 "movl %3, %%ebx\n" /* set %ebx = tst->os_state.exitcode */
170 "int $0x80\n" /* exit(tst->os_state.exitcode) */
171 : "=m" (tst->status)
172 : "n" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode));
173#elif defined(VGP_amd64_linux)
174 asm volatile (
175 "movl %1, %0\n" /* set tst->status = VgTs_Empty */
176 "movq %2, %%rax\n" /* set %rax = __NR_exit */
177 "movq %3, %%rdi\n" /* set %rdi = tst->os_state.exitcode */
178 "syscall\n" /* exit(tst->os_state.exitcode) */
179 : "=m" (tst->status)
180 : "n" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode));
sewardj2c48c7b2005-11-29 13:05:56 +0000181#elif defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
njna3afdfb2005-11-09 04:49:28 +0000182 { UInt vgts_empty = (UInt)VgTs_Empty;
183 asm volatile (
184 "stw %1,%0\n\t" /* set tst->status = VgTs_Empty */
185 "li 0,%2\n\t" /* set r0 = __NR_exit */
186 "lwz 3,%3\n\t" /* set r3 = tst->os_state.exitcode */
187 "sc\n\t" /* exit(tst->os_state.exitcode) */
188 : "=m" (tst->status)
189 : "r" (vgts_empty), "n" (__NR_exit), "m" (tst->os_state.exitcode));
190 }
191#else
192# error Unknown platform
193#endif
194
195 VG_(core_panic)("Thread exit failed?\n");
196 }
197
198 /*NOTREACHED*/
199 vg_assert(0);
200}
201
njnffd9c1d2005-11-10 04:02:19 +0000202Word ML_(start_thread_NORETURN) ( void* arg )
njna3afdfb2005-11-09 04:49:28 +0000203{
204 ThreadState* tst = (ThreadState*)arg;
205 ThreadId tid = tst->tid;
206
njne1486662005-11-10 02:48:04 +0000207 run_a_thread_NORETURN ( (Word)tid );
njna3afdfb2005-11-09 04:49:28 +0000208 /*NOTREACHED*/
209 vg_assert(0);
210}
211
212/* Allocate a stack for this thread, if it doesn't already have one.
213 They're allocated lazily, and never freed. Returns the initial stack
214 pointer value to use, or 0 if allocation failed. */
215Addr ML_(allocstack)(ThreadId tid)
216{
217 ThreadState* tst = VG_(get_ThreadState)(tid);
218 VgStack* stack;
219 Addr initial_SP;
220
221 /* Either the stack_base and stack_init_SP are both zero (in which
222 case a stack hasn't been allocated) or they are both non-zero,
223 in which case it has. */
224
225 if (tst->os_state.valgrind_stack_base == 0)
226 vg_assert(tst->os_state.valgrind_stack_init_SP == 0);
227
228 if (tst->os_state.valgrind_stack_base != 0)
229 vg_assert(tst->os_state.valgrind_stack_init_SP != 0);
230
231 /* If no stack is present, allocate one. */
232
233 if (tst->os_state.valgrind_stack_base == 0) {
234 stack = VG_(am_alloc_VgStack)( &initial_SP );
235 if (stack) {
236 tst->os_state.valgrind_stack_base = (Addr)stack;
237 tst->os_state.valgrind_stack_init_SP = initial_SP;
238 }
239 }
240
241 if (0)
242 VG_(printf)( "stack for tid %d at %p; init_SP=%p\n",
243 tid,
244 (void*)tst->os_state.valgrind_stack_base,
245 (void*)tst->os_state.valgrind_stack_init_SP );
246
247 return tst->os_state.valgrind_stack_init_SP;
248}
249
250/* Allocate a stack for the main thread, and run it all the way to the
251 end. Although we already have a working VgStack
252 (VG_(interim_stack)) it's better to allocate a new one, so that
253 overflow detection works uniformly for all threads.
254*/
255void VG_(main_thread_wrapper_NORETURN)(ThreadId tid)
256{
257 Addr sp;
258 VG_(debugLog)(1, "syswrap-linux",
259 "entering VG_(main_thread_wrapper_NORETURN)\n");
260
261 sp = ML_(allocstack)(tid);
262
263#if defined(VGP_ppc32_linux)
264 /* make a stack frame */
265 sp -= 16;
266 sp &= ~0xF;
267 *(UWord *)sp = 0;
cerion21082042005-12-06 19:07:08 +0000268#elif defined(VGP_ppc64_linux)
269 /* make a stack frame */
270 sp -= 112;
271 sp &= ~((Addr)0xF);
272 *(UWord *)sp = 0;
njna3afdfb2005-11-09 04:49:28 +0000273#endif
274
275 /* If we can't even allocate the first thread's stack, we're hosed.
276 Give up. */
277 vg_assert2(sp != 0, "Cannot allocate main thread's stack.");
278
279 /* shouldn't be any other threads around yet */
280 vg_assert( VG_(count_living_threads)() == 1 );
281
282 ML_(call_on_new_stack_0_1)(
njne1486662005-11-10 02:48:04 +0000283 (Addr)sp, /* stack */
284 0, /* bogus return address */
285 run_a_thread_NORETURN, /* fn to call */
286 (Word)tid /* arg to give it */
njna3afdfb2005-11-09 04:49:28 +0000287 );
288
289 /*NOTREACHED*/
290 vg_assert(0);
291}
292
293
njne1486662005-11-10 02:48:04 +0000294/* Do a clone which is really a fork() */
295SysRes ML_(do_fork_clone) ( ThreadId tid, UInt flags,
296 Int* parent_tidptr, Int* child_tidptr )
297{
298 vki_sigset_t fork_saved_mask;
299 vki_sigset_t mask;
300 SysRes res;
301
302 if (flags & (VKI_CLONE_SETTLS | VKI_CLONE_FS | VKI_CLONE_VM
303 | VKI_CLONE_FILES | VKI_CLONE_VFORK))
304 return VG_(mk_SysRes_Error)( VKI_EINVAL );
305
306 /* Block all signals during fork, so that we can fix things up in
307 the child without being interrupted. */
308 VG_(sigfillset)(&mask);
309 VG_(sigprocmask)(VKI_SIG_SETMASK, &mask, &fork_saved_mask);
310
311 /* Since this is the fork() form of clone, we don't need all that
312 VG_(clone) stuff */
sewardj2c48c7b2005-11-29 13:05:56 +0000313#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
njne1486662005-11-10 02:48:04 +0000314 res = VG_(do_syscall5)( __NR_clone, flags,
315 (UWord)NULL, (UWord)parent_tidptr,
316 (UWord)NULL, (UWord)child_tidptr );
317#elif defined(VGP_amd64_linux)
318 /* note that the last two arguments are the opposite way round to x86 and
319 ppc32 as the amd64 kernel expects the arguments in a different order */
320 res = VG_(do_syscall5)( __NR_clone, flags,
321 (UWord)NULL, (UWord)parent_tidptr,
322 (UWord)child_tidptr, (UWord)NULL );
njne1486662005-11-10 02:48:04 +0000323#else
324# error Unknown platform
325#endif
326
327 if (!res.isError && res.val == 0) {
328 /* child */
329 VG_(do_atfork_child)(tid);
330
331 /* restore signal mask */
332 VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
333 }
334 else
335 if (!res.isError && res.val > 0) {
336 /* parent */
337 if (VG_(clo_trace_syscalls))
338 VG_(printf)(" clone(fork): process %d created child %d\n",
339 VG_(getpid)(), res.val);
340
341 /* restore signal mask */
342 VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
343 }
344
345 return res;
346}
347
348
njna3afdfb2005-11-09 04:49:28 +0000349/* ---------------------------------------------------------------------
nethercotefd453532004-11-17 17:21:12 +0000350 PRE/POST wrappers for arch-generic, Linux-specific syscalls
351 ------------------------------------------------------------------ */
352
353// Nb: See the comment above the generic PRE/POST wrappers in
njnc1b01812005-06-17 22:19:06 +0000354// m_syswrap/syswrap-generic.c for notes about how they work.
nethercotefd453532004-11-17 17:21:12 +0000355
sewardja8d8e232005-06-07 20:04:56 +0000356#define PRE(name) DEFN_PRE_TEMPLATE(linux, name)
357#define POST(name) DEFN_POST_TEMPLATE(linux, name)
nethercotefd453532004-11-17 17:21:12 +0000358
tom20d35722005-07-27 22:57:18 +0000359// Combine two 32-bit values into a 64-bit value
360#define LOHI64(lo,hi) ( (lo) | ((ULong)(hi) << 32) )
361
njn73975482005-08-30 02:45:44 +0000362/* ---------------------------------------------------------------------
363 *mount wrappers
364 ------------------------------------------------------------------ */
sewardjb5f6f512005-03-10 23:59:00 +0000365
sewardja8d8e232005-06-07 20:04:56 +0000366PRE(sys_mount)
nethercotefd453532004-11-17 17:21:12 +0000367{
368 // Nb: depending on 'flags', the 'type' and 'data' args may be ignored.
369 // We are conservative and check everything, except the memory pointed to
370 // by 'data'.
sewardja8d8e232005-06-07 20:04:56 +0000371 *flags |= SfMayBlock;
sewardjb5f6f512005-03-10 23:59:00 +0000372 PRINT( "sys_mount( %p, %p, %p, %p, %p )" ,ARG1,ARG2,ARG3,ARG4,ARG5);
nethercotefd453532004-11-17 17:21:12 +0000373 PRE_REG_READ5(long, "mount",
374 char *, source, char *, target, char *, type,
375 unsigned long, flags, void *, data);
njn22cfccb2004-11-27 16:10:23 +0000376 PRE_MEM_RASCIIZ( "mount(source)", ARG1);
377 PRE_MEM_RASCIIZ( "mount(target)", ARG2);
378 PRE_MEM_RASCIIZ( "mount(type)", ARG3);
nethercotefd453532004-11-17 17:21:12 +0000379}
380
sewardja8d8e232005-06-07 20:04:56 +0000381PRE(sys_oldumount)
nethercotefd453532004-11-17 17:21:12 +0000382{
njn22cfccb2004-11-27 16:10:23 +0000383 PRINT("sys_oldumount( %p )", ARG1);
nethercotefd453532004-11-17 17:21:12 +0000384 PRE_REG_READ1(long, "umount", char *, path);
njn22cfccb2004-11-27 16:10:23 +0000385 PRE_MEM_RASCIIZ( "umount(path)", ARG1);
nethercotefd453532004-11-17 17:21:12 +0000386}
387
sewardja8d8e232005-06-07 20:04:56 +0000388PRE(sys_umount)
nethercotefd453532004-11-17 17:21:12 +0000389{
njn4ae40402005-08-24 13:55:59 +0000390 PRINT("sys_umount( %p, %d )", ARG1, ARG2);
nethercotefd453532004-11-17 17:21:12 +0000391 PRE_REG_READ2(long, "umount2", char *, path, int, flags);
njn22cfccb2004-11-27 16:10:23 +0000392 PRE_MEM_RASCIIZ( "umount2(path)", ARG1);
nethercotefd453532004-11-17 17:21:12 +0000393}
394
njn73975482005-08-30 02:45:44 +0000395/* ---------------------------------------------------------------------
396 16- and 32-bit uid/gid wrappers
397 ------------------------------------------------------------------ */
sewardj696c5512005-06-08 23:38:32 +0000398
399PRE(sys_setfsuid16)
400{
401 PRINT("sys_setfsuid16 ( %d )", ARG1);
402 PRE_REG_READ1(long, "setfsuid16", vki_old_uid_t, uid);
403}
404
sewardje6d5e722005-06-10 10:27:55 +0000405PRE(sys_setfsuid)
406{
407 PRINT("sys_setfsuid ( %d )", ARG1);
408 PRE_REG_READ1(long, "setfsuid", vki_uid_t, uid);
409}
sewardj696c5512005-06-08 23:38:32 +0000410
411PRE(sys_setfsgid16)
412{
413 PRINT("sys_setfsgid16 ( %d )", ARG1);
414 PRE_REG_READ1(long, "setfsgid16", vki_old_gid_t, gid);
415}
416
sewardje6d5e722005-06-10 10:27:55 +0000417PRE(sys_setfsgid)
418{
419 PRINT("sys_setfsgid ( %d )", ARG1);
420 PRE_REG_READ1(long, "setfsgid", vki_gid_t, gid);
421}
422
423PRE(sys_setresuid16)
424{
425 PRINT("sys_setresuid16 ( %d, %d, %d )", ARG1, ARG2, ARG3);
426 PRE_REG_READ3(long, "setresuid16",
427 vki_old_uid_t, ruid, vki_old_uid_t, euid, vki_old_uid_t, suid);
428}
429
430PRE(sys_setresuid)
431{
432 PRINT("sys_setresuid ( %d, %d, %d )", ARG1, ARG2, ARG3);
433 PRE_REG_READ3(long, "setresuid",
434 vki_uid_t, ruid, vki_uid_t, euid, vki_uid_t, suid);
435}
436
437PRE(sys_getresuid16)
438{
439 PRINT("sys_getresuid16 ( %p, %p, %p )", ARG1,ARG2,ARG3);
440 PRE_REG_READ3(long, "getresuid16",
441 vki_old_uid_t *, ruid, vki_old_uid_t *, euid,
442 vki_old_uid_t *, suid);
443 PRE_MEM_WRITE( "getresuid16(ruid)", ARG1, sizeof(vki_old_uid_t) );
444 PRE_MEM_WRITE( "getresuid16(euid)", ARG2, sizeof(vki_old_uid_t) );
445 PRE_MEM_WRITE( "getresuid16(suid)", ARG3, sizeof(vki_old_uid_t) );
446}
447POST(sys_getresuid16)
448{
449 vg_assert(SUCCESS);
450 if (RES == 0) {
451 POST_MEM_WRITE( ARG1, sizeof(vki_old_uid_t) );
452 POST_MEM_WRITE( ARG2, sizeof(vki_old_uid_t) );
453 POST_MEM_WRITE( ARG3, sizeof(vki_old_uid_t) );
454 }
455}
sewardj78b50e42005-06-08 01:47:28 +0000456
457PRE(sys_getresuid)
458{
459 PRINT("sys_getresuid ( %p, %p, %p )", ARG1,ARG2,ARG3);
460 PRE_REG_READ3(long, "getresuid",
461 vki_uid_t *, ruid, vki_uid_t *, euid, vki_uid_t *, suid);
462 PRE_MEM_WRITE( "getresuid(ruid)", ARG1, sizeof(vki_uid_t) );
463 PRE_MEM_WRITE( "getresuid(euid)", ARG2, sizeof(vki_uid_t) );
464 PRE_MEM_WRITE( "getresuid(suid)", ARG3, sizeof(vki_uid_t) );
465}
sewardj78b50e42005-06-08 01:47:28 +0000466POST(sys_getresuid)
467{
468 vg_assert(SUCCESS);
469 if (RES == 0) {
470 POST_MEM_WRITE( ARG1, sizeof(vki_uid_t) );
471 POST_MEM_WRITE( ARG2, sizeof(vki_uid_t) );
472 POST_MEM_WRITE( ARG3, sizeof(vki_uid_t) );
473 }
474}
475
sewardje6d5e722005-06-10 10:27:55 +0000476PRE(sys_setresgid16)
477{
478 PRINT("sys_setresgid16 ( %d, %d, %d )", ARG1, ARG2, ARG3);
479 PRE_REG_READ3(long, "setresgid16",
480 vki_old_gid_t, rgid,
481 vki_old_gid_t, egid, vki_old_gid_t, sgid);
482}
483
484PRE(sys_setresgid)
485{
486 PRINT("sys_setresgid ( %d, %d, %d )", ARG1, ARG2, ARG3);
487 PRE_REG_READ3(long, "setresgid",
488 vki_gid_t, rgid, vki_gid_t, egid, vki_gid_t, sgid);
489}
490
491PRE(sys_getresgid16)
492{
493 PRINT("sys_getresgid16 ( %p, %p, %p )", ARG1,ARG2,ARG3);
494 PRE_REG_READ3(long, "getresgid16",
495 vki_old_gid_t *, rgid, vki_old_gid_t *, egid,
496 vki_old_gid_t *, sgid);
497 PRE_MEM_WRITE( "getresgid16(rgid)", ARG1, sizeof(vki_old_gid_t) );
498 PRE_MEM_WRITE( "getresgid16(egid)", ARG2, sizeof(vki_old_gid_t) );
499 PRE_MEM_WRITE( "getresgid16(sgid)", ARG3, sizeof(vki_old_gid_t) );
500}
501POST(sys_getresgid16)
502{
503 vg_assert(SUCCESS);
504 if (RES == 0) {
505 POST_MEM_WRITE( ARG1, sizeof(vki_old_gid_t) );
506 POST_MEM_WRITE( ARG2, sizeof(vki_old_gid_t) );
507 POST_MEM_WRITE( ARG3, sizeof(vki_old_gid_t) );
508 }
509}
sewardj78b50e42005-06-08 01:47:28 +0000510
511PRE(sys_getresgid)
512{
513 PRINT("sys_getresgid ( %p, %p, %p )", ARG1,ARG2,ARG3);
514 PRE_REG_READ3(long, "getresgid",
515 vki_gid_t *, rgid, vki_gid_t *, egid, vki_gid_t *, sgid);
516 PRE_MEM_WRITE( "getresgid(rgid)", ARG1, sizeof(vki_gid_t) );
517 PRE_MEM_WRITE( "getresgid(egid)", ARG2, sizeof(vki_gid_t) );
518 PRE_MEM_WRITE( "getresgid(sgid)", ARG3, sizeof(vki_gid_t) );
519}
sewardj78b50e42005-06-08 01:47:28 +0000520POST(sys_getresgid)
521{
522 vg_assert(SUCCESS);
523 if (RES == 0) {
524 POST_MEM_WRITE( ARG1, sizeof(vki_gid_t) );
525 POST_MEM_WRITE( ARG2, sizeof(vki_gid_t) );
526 POST_MEM_WRITE( ARG3, sizeof(vki_gid_t) );
527 }
528}
529
njn73975482005-08-30 02:45:44 +0000530/* ---------------------------------------------------------------------
531 miscellaneous wrappers
532 ------------------------------------------------------------------ */
533
534PRE(sys_exit_group)
535{
536 ThreadId t;
537 ThreadState* tst;
538
539 PRINT("exit_group( %d )", ARG1);
540 PRE_REG_READ1(void, "exit_group", int, exit_code);
541
542 tst = VG_(get_ThreadState)(tid);
543
544 /* A little complex; find all the threads with the same threadgroup
545 as this one (including this one), and mark them to exit */
546 for (t = 1; t < VG_N_THREADS; t++) {
547 if ( /* not alive */
548 VG_(threads)[t].status == VgTs_Empty
549 ||
550 /* not our group */
551 VG_(threads)[t].os_state.threadgroup != tst->os_state.threadgroup
552 )
553 continue;
554
555 VG_(threads)[t].exitreason = VgSrc_ExitSyscall;
556 VG_(threads)[t].os_state.exitcode = ARG1;
557
558 if (t != tid)
559 VG_(kill_thread)(t); /* unblock it, if blocked */
560 }
561
562 /* We have to claim the syscall already succeeded. */
563 SET_STATUS_Success(0);
564}
565
566PRE(sys_llseek)
567{
568 PRINT("sys_llseek ( %d, 0x%x, 0x%x, %p, %d )", ARG1,ARG2,ARG3,ARG4,ARG5);
569 PRE_REG_READ5(long, "llseek",
570 unsigned int, fd, unsigned long, offset_high,
571 unsigned long, offset_low, vki_loff_t *, result,
572 unsigned int, whence);
573 PRE_MEM_WRITE( "llseek(result)", ARG4, sizeof(vki_loff_t));
574}
575POST(sys_llseek)
576{
577 vg_assert(SUCCESS);
578 if (RES == 0)
579 POST_MEM_WRITE( ARG4, sizeof(vki_loff_t) );
580}
581
582//zz PRE(sys_adjtimex, 0)
583//zz {
584//zz struct vki_timex *tx = (struct vki_timex *)ARG1;
585//zz PRINT("sys_adjtimex ( %p )", ARG1);
586//zz PRE_REG_READ1(long, "adjtimex", struct timex *, buf);
587//zz PRE_MEM_READ( "adjtimex(timex->modes)", ARG1, sizeof(tx->modes));
588//zz
589#if 0 //zz (avoiding warnings about multi-line comments)
590zz #define ADJX(bit,field) \
591zz if (tx->modes & bit) \
592zz PRE_MEM_READ( "adjtimex(timex->"#field")", \
593zz (Addr)&tx->field, sizeof(tx->field))
594#endif
595//zz ADJX(ADJ_FREQUENCY, freq);
596//zz ADJX(ADJ_MAXERROR, maxerror);
597//zz ADJX(ADJ_ESTERROR, esterror);
598//zz ADJX(ADJ_STATUS, status);
599//zz ADJX(ADJ_TIMECONST, constant);
600//zz ADJX(ADJ_TICK, tick);
601//zz #undef ADJX
602//zz
603//zz PRE_MEM_WRITE( "adjtimex(timex)", ARG1, sizeof(struct vki_timex));
604//zz }
605//zz
606//zz POST(sys_adjtimex)
607//zz {
608//zz POST_MEM_WRITE( ARG1, sizeof(struct vki_timex) );
609//zz }
610
sewardj696c5512005-06-08 23:38:32 +0000611PRE(sys_ioperm)
612{
613 PRINT("sys_ioperm ( %d, %d, %d )", ARG1, ARG2, ARG3 );
614 PRE_REG_READ3(long, "ioperm",
615 unsigned long, from, unsigned long, num, int, turn_on);
616}
617
618PRE(sys_syslog)
619{
620 *flags |= SfMayBlock;
621 PRINT("sys_syslog (%d, %p, %d)", ARG1,ARG2,ARG3);
622 PRE_REG_READ3(long, "syslog", int, type, char *, bufp, int, len);
623 switch (ARG1) {
624 // The kernel uses magic numbers here, rather than named constants,
625 // therefore so do we.
626 case 2: case 3: case 4:
627 PRE_MEM_WRITE( "syslog(bufp)", ARG2, ARG3);
628 break;
629 default:
630 break;
631 }
632}
sewardj696c5512005-06-08 23:38:32 +0000633POST(sys_syslog)
634{
635 switch (ARG1) {
636 case 2: case 3: case 4:
637 POST_MEM_WRITE( ARG2, ARG3 );
638 break;
639 default:
640 break;
641 }
642}
643
644PRE(sys_vhangup)
645{
646 PRINT("sys_vhangup ( )");
647 PRE_REG_READ0(long, "vhangup");
648}
649
650PRE(sys_sysinfo)
651{
652 PRINT("sys_sysinfo ( %p )",ARG1);
653 PRE_REG_READ1(long, "sysinfo", struct sysinfo *, info);
654 PRE_MEM_WRITE( "sysinfo(info)", ARG1, sizeof(struct vki_sysinfo) );
655}
sewardj696c5512005-06-08 23:38:32 +0000656POST(sys_sysinfo)
657{
658 POST_MEM_WRITE( ARG1, sizeof(struct vki_sysinfo) );
659}
660
661PRE(sys_personality)
662{
663 PRINT("sys_personality ( %llu )", (ULong)ARG1);
664 PRE_REG_READ1(long, "personality", vki_u_long, persona);
665}
nethercotefd453532004-11-17 17:21:12 +0000666
sewardja8d8e232005-06-07 20:04:56 +0000667PRE(sys_sysctl)
nethercotefd453532004-11-17 17:21:12 +0000668{
sewardje6d5e722005-06-10 10:27:55 +0000669 struct __vki_sysctl_args *args;
sewardjf308fd82005-03-14 19:52:16 +0000670 PRINT("sys_sysctl ( %p )", ARG1 );
sewardje6d5e722005-06-10 10:27:55 +0000671 args = (struct __vki_sysctl_args *)ARG1;
672 PRE_REG_READ1(long, "sysctl", struct __sysctl_args *, args);
njn22cfccb2004-11-27 16:10:23 +0000673 PRE_MEM_WRITE( "sysctl(args)", ARG1, sizeof(struct __vki_sysctl_args) );
sewardj45f4e7c2005-09-27 19:20:21 +0000674 if (!VG_(am_is_valid_for_client)(ARG1, sizeof(struct __vki_sysctl_args),
675 VKI_PROT_READ)) {
sewardja8d8e232005-06-07 20:04:56 +0000676 SET_STATUS_Failure( VKI_EFAULT );
sewardjb5f6f512005-03-10 23:59:00 +0000677 return;
678 }
679
sewardje6d5e722005-06-10 10:27:55 +0000680 PRE_MEM_READ("sysctl(name)", (Addr)args->name, args->nlen * sizeof(*args->name));
681 if (args->newval != NULL)
682 PRE_MEM_READ("sysctl(newval)", (Addr)args->newval, args->newlen);
683 if (args->oldlenp != NULL) {
684 PRE_MEM_READ("sysctl(oldlenp)", (Addr)args->oldlenp, sizeof(*args->oldlenp));
685 PRE_MEM_WRITE("sysctl(oldval)", (Addr)args->oldval, *args->oldlenp);
sewardjb5f6f512005-03-10 23:59:00 +0000686 }
nethercotefd453532004-11-17 17:21:12 +0000687}
nethercotefd453532004-11-17 17:21:12 +0000688POST(sys_sysctl)
689{
sewardje6d5e722005-06-10 10:27:55 +0000690 struct __vki_sysctl_args *args;
691 args = (struct __vki_sysctl_args *)ARG1;
692 if (args->oldlenp != NULL) {
693 POST_MEM_WRITE((Addr)args->oldlenp, sizeof(*args->oldlenp));
694 POST_MEM_WRITE((Addr)args->oldval, 1 + *args->oldlenp);
sewardjb5f6f512005-03-10 23:59:00 +0000695 }
nethercotefd453532004-11-17 17:21:12 +0000696}
697
sewardje6d5e722005-06-10 10:27:55 +0000698PRE(sys_prctl)
699{
700 *flags |= SfMayBlock;
701 PRINT( "prctl ( %d, %d, %d, %d, %d )", ARG1, ARG2, ARG3, ARG4, ARG5 );
702 // XXX: too simplistic, often not all args are used
703 // Nb: can't use "ARG2".."ARG5" here because that's our own macro...
704 PRE_REG_READ5(long, "prctl",
705 int, option, unsigned long, arg2, unsigned long, arg3,
706 unsigned long, arg4, unsigned long, arg5);
707 // XXX: totally wrong... we need to look at the 'option' arg, and do
708 // PRE_MEM_READs/PRE_MEM_WRITEs as necessary...
709}
710
711PRE(sys_sendfile)
712{
713 *flags |= SfMayBlock;
njn68e46592005-08-26 19:42:27 +0000714 PRINT("sys_sendfile ( %d, %d, %p, %lu )", ARG1,ARG2,ARG3,ARG4);
sewardje6d5e722005-06-10 10:27:55 +0000715 PRE_REG_READ4(ssize_t, "sendfile",
716 int, out_fd, int, in_fd, vki_off_t *, offset,
717 vki_size_t, count);
718 if (ARG3 != 0)
719 PRE_MEM_WRITE( "sendfile(offset)", ARG3, sizeof(vki_off_t) );
720}
721POST(sys_sendfile)
722{
723 if (ARG3 != 0 ) {
724 POST_MEM_WRITE( ARG3, sizeof( vki_off_t ) );
725 }
726}
727
728PRE(sys_sendfile64)
729{
730 *flags |= SfMayBlock;
njn68e46592005-08-26 19:42:27 +0000731 PRINT("sendfile64 ( %d, %d, %p, %lu )",ARG1,ARG2,ARG3,ARG4);
sewardje6d5e722005-06-10 10:27:55 +0000732 PRE_REG_READ4(ssize_t, "sendfile64",
733 int, out_fd, int, in_fd, vki_loff_t *, offset,
734 vki_size_t, count);
735 if (ARG3 != 0)
736 PRE_MEM_WRITE( "sendfile64(offset)", ARG3, sizeof(vki_loff_t) );
737}
738POST(sys_sendfile64)
739{
740 if (ARG3 != 0 ) {
741 POST_MEM_WRITE( ARG3, sizeof(vki_loff_t) );
742 }
743}
sewardjbc22cf72005-06-08 00:02:49 +0000744
745PRE(sys_futex)
746{
747 /*
748 arg param used by ops
749
750 ARG1 - u32 *futex all
751 ARG2 - int op
752 ARG3 - int val WAIT,WAKE,FD,REQUEUE,CMP_REQUEUE
753 ARG4 - struct timespec *utime WAIT:time* REQUEUE,CMP_REQUEUE:val2
754 ARG5 - u32 *uaddr2 REQUEUE,CMP_REQUEUE
755 ARG6 - int val3 CMP_REQUEUE
756 */
757 PRINT("sys_futex ( %p, %d, %d, %p, %p )", ARG1,ARG2,ARG3,ARG4,ARG5);
tomf26b6bf2006-06-07 17:47:51 +0000758 switch(ARG2) {
759 case VKI_FUTEX_CMP_REQUEUE:
760 PRE_REG_READ6(long, "futex",
761 vki_u32 *, futex, int, op, int, val,
762 struct timespec *, utime, vki_u32 *, uaddr2, int, val3);
763 break;
764 case VKI_FUTEX_REQUEUE:
765 PRE_REG_READ5(long, "futex",
766 vki_u32 *, futex, int, op, int, val,
767 struct timespec *, utime, vki_u32 *, uaddr2);
768 break;
769 case VKI_FUTEX_WAIT:
770 PRE_REG_READ4(long, "futex",
771 vki_u32 *, futex, int, op, int, val,
772 struct timespec *, utime);
773 break;
774 case VKI_FUTEX_WAKE:
775 case VKI_FUTEX_FD:
776 PRE_REG_READ3(long, "futex",
777 vki_u32 *, futex, int, op, int, val);
778 break;
779 default:
780 PRE_REG_READ2(long, "futex", vki_u32 *, futex, int, op);
781 break;
782 }
sewardjbc22cf72005-06-08 00:02:49 +0000783
784 PRE_MEM_READ( "futex(futex)", ARG1, sizeof(Int) );
785
786 *flags |= SfMayBlock;
787
788 switch(ARG2) {
789 case VKI_FUTEX_WAIT:
790 if (ARG4 != 0)
791 PRE_MEM_READ( "futex(timeout)", ARG4, sizeof(struct vki_timespec) );
792 break;
793
794 case VKI_FUTEX_REQUEUE:
795 case VKI_FUTEX_CMP_REQUEUE:
796 PRE_MEM_READ( "futex(futex2)", ARG5, sizeof(Int) );
797 break;
798
799 case VKI_FUTEX_WAKE:
800 case VKI_FUTEX_FD:
801 /* no additional pointers */
802 break;
803
804 default:
805 SET_STATUS_Failure( VKI_ENOSYS ); // some futex function we don't understand
806 break;
807 }
808}
sewardjbc22cf72005-06-08 00:02:49 +0000809POST(sys_futex)
810{
811 vg_assert(SUCCESS);
812 POST_MEM_WRITE( ARG1, sizeof(int) );
813 if (ARG2 == VKI_FUTEX_FD) {
sewardj7eb7c582005-06-23 01:02:53 +0000814 if (!ML_(fd_allowed)(RES, "futex", tid, True)) {
sewardjbc22cf72005-06-08 00:02:49 +0000815 VG_(close)(RES);
816 SET_STATUS_Failure( VKI_EMFILE );
817 } else {
818 if (VG_(clo_track_fds))
njnf845f8f2005-06-23 02:26:47 +0000819 ML_(record_fd_open_nameless)(tid, RES);
sewardjbc22cf72005-06-08 00:02:49 +0000820 }
821 }
822}
823
tom05b1f9a2006-05-17 14:24:12 +0000824PRE(sys_set_robust_list)
825{
826 PRINT("sys_set_robust_list ( %p, %d )", ARG1,ARG2);
827 PRE_REG_READ2(long, "set_robust_list",
828 struct vki_robust_list_head *, head, vki_size_t, len);
829
830 /* Just check the robust_list_head structure is readable - don't
831 try and chase the list as the kernel will only read it when
832 the thread exits so the current contents is irrelevant. */
833 if (ARG1 != 0)
834 PRE_MEM_READ("set_robust_list(head)", ARG1, ARG2);
835}
836
837PRE(sys_get_robust_list)
838{
839 PRINT("sys_get_robust_list ( %d, %p, %d )", ARG1,ARG2,ARG3);
840 PRE_REG_READ3(long, "get_robust_list",
841 int, pid,
842 struct vki_robust_list_head **, head_ptr,
843 vki_size_t *, len_ptr);
844 PRE_MEM_WRITE("get_robust_list(head_ptr)",
845 ARG2, sizeof(struct vki_robust_list_head *));
846 PRE_MEM_WRITE("get_robust_list(len_ptr)",
847 ARG3, sizeof(struct vki_size_t *));
848}
849POST(sys_get_robust_list)
850{
851 POST_MEM_WRITE(ARG2, sizeof(struct vki_robust_list_head *));
852 POST_MEM_WRITE(ARG3, sizeof(struct vki_size_t *));
853}
854
tom363ec762006-03-21 10:58:35 +0000855PRE(sys_pselect6)
856{
857 *flags |= SfMayBlock;
858 PRINT("sys_pselect6 ( %d, %p, %p, %p, %p, %p )", ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
859 PRE_REG_READ6(long, "pselect6",
860 int, n, vki_fd_set *, readfds, vki_fd_set *, writefds,
861 vki_fd_set *, exceptfds, struct vki_timeval *, timeout,
862 void *, sig);
863 // XXX: this possibly understates how much memory is read.
864 if (ARG2 != 0)
865 PRE_MEM_READ( "pselect6(readfds)",
866 ARG2, ARG1/8 /* __FD_SETSIZE/8 */ );
867 if (ARG3 != 0)
868 PRE_MEM_READ( "pselect6(writefds)",
869 ARG3, ARG1/8 /* __FD_SETSIZE/8 */ );
870 if (ARG4 != 0)
871 PRE_MEM_READ( "pselect6(exceptfds)",
872 ARG4, ARG1/8 /* __FD_SETSIZE/8 */ );
873 if (ARG5 != 0)
874 PRE_MEM_READ( "pselect6(timeout)", ARG5, sizeof(struct vki_timeval) );
875 if (ARG6 != 0)
876 PRE_MEM_READ( "pselect6(sig)", ARG6, sizeof(void *)+sizeof(vki_size_t) );
877}
878
879PRE(sys_ppoll)
880{
881 UInt i;
882 struct vki_pollfd* ufds = (struct vki_pollfd *)ARG1;
883 *flags |= SfMayBlock;
884 PRINT("sys_ppoll ( %p, %d, %p, %p, %llu )\n", ARG1,ARG2,ARG3,ARG4,ARG5);
885 PRE_REG_READ5(long, "ppoll",
886 struct vki_pollfd *, ufds, unsigned int, nfds,
887 struct vki_timespec *, tsp, vki_sigset_t *, sigmask,
888 vki_size_t, sigsetsize);
889
890 for (i = 0; i < ARG2; i++) {
891 PRE_MEM_READ( "ppoll(ufds.fd)",
892 (Addr)(&ufds[i].fd), sizeof(ufds[i].fd) );
893 PRE_MEM_READ( "ppoll(ufds.events)",
894 (Addr)(&ufds[i].events), sizeof(ufds[i].events) );
895 PRE_MEM_WRITE( "ppoll(ufd.reventss)",
896 (Addr)(&ufds[i].revents), sizeof(ufds[i].revents) );
897 }
898
899 if (ARG3)
900 PRE_MEM_READ( "ppoll(tsp)", ARG3, sizeof(struct vki_timespec) );
901 if (ARG4)
902 PRE_MEM_READ( "ppoll(sigmask)", ARG4, sizeof(vki_sigset_t) );
903}
904
905POST(sys_ppoll)
906{
907 if (RES > 0) {
908 UInt i;
909 struct vki_pollfd* ufds = (struct vki_pollfd *)ARG1;
910 for (i = 0; i < ARG2; i++)
911 POST_MEM_WRITE( (Addr)(&ufds[i].revents), sizeof(ufds[i].revents) );
912 }
913}
914
njn5c691752005-08-31 03:00:40 +0000915
njn73975482005-08-30 02:45:44 +0000916/* ---------------------------------------------------------------------
917 epoll_* wrappers
918 ------------------------------------------------------------------ */
919
sewardje6d5e722005-06-10 10:27:55 +0000920PRE(sys_epoll_create)
921{
922 PRINT("sys_epoll_create ( %d )", ARG1);
923 PRE_REG_READ1(long, "epoll_create", int, size);
924}
925POST(sys_epoll_create)
926{
927 vg_assert(SUCCESS);
sewardj7eb7c582005-06-23 01:02:53 +0000928 if (!ML_(fd_allowed)(RES, "epoll_create", tid, True)) {
sewardje6d5e722005-06-10 10:27:55 +0000929 VG_(close)(RES);
930 SET_STATUS_Failure( VKI_EMFILE );
931 } else {
932 if (VG_(clo_track_fds))
njnf845f8f2005-06-23 02:26:47 +0000933 ML_(record_fd_open_nameless) (tid, RES);
sewardje6d5e722005-06-10 10:27:55 +0000934 }
935}
936
937PRE(sys_epoll_ctl)
938{
939 static const HChar* epoll_ctl_s[3] = {
940 "EPOLL_CTL_ADD",
941 "EPOLL_CTL_DEL",
942 "EPOLL_CTL_MOD"
943 };
944 PRINT("sys_epoll_ctl ( %d, %s, %d, %p )",
945 ARG1, ( ARG2<3 ? epoll_ctl_s[ARG2] : "?" ), ARG3, ARG4);
946 PRE_REG_READ4(long, "epoll_ctl",
njn40e73582005-06-24 21:41:28 +0000947 int, epfd, int, op, int, fd, struct vki_epoll_event *, event);
948 if (ARG2 != VKI_EPOLL_CTL_DEL)
949 PRE_MEM_READ( "epoll_ctl(event)", ARG4, sizeof(struct vki_epoll_event) );
sewardje6d5e722005-06-10 10:27:55 +0000950}
951
952PRE(sys_epoll_wait)
953{
954 *flags |= SfMayBlock;
955 PRINT("sys_epoll_wait ( %d, %p, %d, %d )", ARG1, ARG2, ARG3, ARG4);
956 PRE_REG_READ4(long, "epoll_wait",
njn40e73582005-06-24 21:41:28 +0000957 int, epfd, struct vki_epoll_event *, events,
sewardje6d5e722005-06-10 10:27:55 +0000958 int, maxevents, int, timeout);
njn40e73582005-06-24 21:41:28 +0000959 PRE_MEM_WRITE( "epoll_wait(events)", ARG2, sizeof(struct vki_epoll_event)*ARG3);
sewardje6d5e722005-06-10 10:27:55 +0000960}
961POST(sys_epoll_wait)
962{
963 vg_assert(SUCCESS);
964 if (RES > 0)
njn40e73582005-06-24 21:41:28 +0000965 POST_MEM_WRITE( ARG2, sizeof(struct vki_epoll_event)*RES ) ;
sewardje6d5e722005-06-10 10:27:55 +0000966}
sewardj8c257322005-06-08 01:01:48 +0000967
njn73975482005-08-30 02:45:44 +0000968/* ---------------------------------------------------------------------
969 tid-related wrappers
970 ------------------------------------------------------------------ */
971
sewardj8c257322005-06-08 01:01:48 +0000972PRE(sys_gettid)
973{
974 PRINT("sys_gettid ()");
975 PRE_REG_READ0(long, "gettid");
976}
977
njn73975482005-08-30 02:45:44 +0000978PRE(sys_set_tid_address)
979{
980 PRINT("sys_set_tid_address ( %p )", ARG1);
981 PRE_REG_READ1(long, "set_tid_address", int *, tidptr);
982}
983
tomc8cfca62006-02-15 10:34:50 +0000984PRE(sys_tkill)
985{
986 PRINT("sys_tgkill ( %d, %d )", ARG1,ARG2);
987 PRE_REG_READ2(long, "tkill", int, tid, int, sig);
988 if (!ML_(client_signal_OK)(ARG2)) {
989 SET_STATUS_Failure( VKI_EINVAL );
990 return;
991 }
992
993 /* Check to see if this kill gave us a pending signal */
994 *flags |= SfPollAfter;
995
996 if (VG_(clo_trace_signals))
997 VG_(message)(Vg_DebugMsg, "tkill: sending signal %d to pid %d",
998 ARG2, ARG1);
999
1000 /* If we're sending SIGKILL, check to see if the target is one of
1001 our threads and handle it specially. */
1002 if (ARG2 == VKI_SIGKILL && ML_(do_sigkill)(ARG1, -1)) {
1003 SET_STATUS_Success(0);
1004 return;
1005 }
1006
1007 /* Ask to handle this syscall via the slow route, since that's the
1008 only one that sets tst->status to VgTs_WaitSys. If the result
1009 of doing the syscall is an immediate run of
1010 async_signalhandler() in m_signals, then we need the thread to
1011 be properly tidied away. I have the impression the previous
1012 version of this wrapper worked on x86/amd64 only because the
1013 kernel did not immediately deliver the async signal to this
1014 thread (on ppc it did, which broke the assertion re tst->status
1015 at the top of async_signalhandler()). */
1016 *flags |= SfMayBlock;
1017}
1018POST(sys_tkill)
1019{
1020 if (VG_(clo_trace_signals))
1021 VG_(message)(Vg_DebugMsg, "tkill: sent signal %d to pid %d",
1022 ARG2, ARG1);
1023}
sewardjbc22cf72005-06-08 00:02:49 +00001024
1025PRE(sys_tgkill)
1026{
sewardjbc22cf72005-06-08 00:02:49 +00001027 PRINT("sys_tgkill ( %d, %d, %d )", ARG1,ARG2,ARG3);
1028 PRE_REG_READ3(long, "tgkill", int, tgid, int, tid, int, sig);
sewardj7eb7c582005-06-23 01:02:53 +00001029 if (!ML_(client_signal_OK)(ARG3)) {
sewardjbc22cf72005-06-08 00:02:49 +00001030 SET_STATUS_Failure( VKI_EINVAL );
1031 return;
1032 }
1033
sewardjbc22cf72005-06-08 00:02:49 +00001034 /* Check to see if this kill gave us a pending signal */
1035 *flags |= SfPollAfter;
sewardjd6e91bc2005-11-17 14:26:52 +00001036
1037 if (VG_(clo_trace_signals))
1038 VG_(message)(Vg_DebugMsg, "tgkill: sending signal %d to pid %d/%d",
1039 ARG3, ARG1, ARG2);
1040
1041 /* If we're sending SIGKILL, check to see if the target is one of
1042 our threads and handle it specially. */
1043 if (ARG3 == VKI_SIGKILL && ML_(do_sigkill)(ARG2, ARG1)) {
1044 SET_STATUS_Success(0);
1045 return;
1046 }
1047
1048 /* Ask to handle this syscall via the slow route, since that's the
1049 only one that sets tst->status to VgTs_WaitSys. If the result
1050 of doing the syscall is an immediate run of
1051 async_signalhandler() in m_signals, then we need the thread to
1052 be properly tidied away. I have the impression the previous
1053 version of this wrapper worked on x86/amd64 only because the
1054 kernel did not immediately deliver the async signal to this
1055 thread (on ppc it did, which broke the assertion re tst->status
1056 at the top of async_signalhandler()). */
1057 *flags |= SfMayBlock;
sewardjbc22cf72005-06-08 00:02:49 +00001058}
sewardjbc22cf72005-06-08 00:02:49 +00001059POST(sys_tgkill)
1060{
1061 if (VG_(clo_trace_signals))
1062 VG_(message)(Vg_DebugMsg, "tgkill: sent signal %d to pid %d/%d",
1063 ARG3, ARG1, ARG2);
1064}
1065
njn73975482005-08-30 02:45:44 +00001066/* ---------------------------------------------------------------------
1067 fadvise64* wrappers
1068 ------------------------------------------------------------------ */
1069
tom72440832005-06-15 10:31:10 +00001070PRE(sys_fadvise64)
1071{
tom20d35722005-07-27 22:57:18 +00001072 PRINT("sys_fadvise64 ( %d, %lld, %lu, %d )",
1073 ARG1, LOHI64(ARG2,ARG3), ARG4, ARG5);
1074 PRE_REG_READ5(long, "fadvise64",
1075 int, fd, vki_u32, offset_low, vki_u32, offset_high,
1076 vki_size_t, len, int, advice);
tom72440832005-06-15 10:31:10 +00001077}
1078
1079PRE(sys_fadvise64_64)
1080{
tom20d35722005-07-27 22:57:18 +00001081 PRINT("sys_fadvise64_64 ( %d, %lld, %lld, %d )",
1082 ARG1, LOHI64(ARG2,ARG3), LOHI64(ARG4,ARG5), ARG6);
1083 PRE_REG_READ6(long, "fadvise64_64",
1084 int, fd, vki_u32, offset_low, vki_u32, offset_high,
1085 vki_u32, len_low, vki_u32, len_high, int, advice);
tom72440832005-06-15 10:31:10 +00001086}
sewardje6d5e722005-06-10 10:27:55 +00001087
njn73975482005-08-30 02:45:44 +00001088/* ---------------------------------------------------------------------
1089 io_* wrappers
1090 ------------------------------------------------------------------ */
1091
sewardje6d5e722005-06-10 10:27:55 +00001092// Nb: this wrapper has to pad/unpad memory around the syscall itself,
1093// and this allows us to control exactly the code that gets run while
1094// the padding is in place.
sewardj45f4e7c2005-09-27 19:20:21 +00001095
sewardje6d5e722005-06-10 10:27:55 +00001096PRE(sys_io_setup)
1097{
sewardje6d5e722005-06-10 10:27:55 +00001098 PRINT("sys_io_setup ( %u, %p )", ARG1,ARG2);
1099 PRE_REG_READ2(long, "io_setup",
1100 unsigned, nr_events, vki_aio_context_t *, ctxp);
1101 PRE_MEM_WRITE( "io_setup(ctxp)", ARG2, sizeof(vki_aio_context_t) );
sewardj45f4e7c2005-09-27 19:20:21 +00001102}
1103
1104POST(sys_io_setup)
1105{
1106 SizeT size;
1107 struct vki_aio_ring *r;
1108
sewardje6d5e722005-06-10 10:27:55 +00001109 size = VG_PGROUNDUP(sizeof(struct vki_aio_ring) +
1110 ARG1*sizeof(struct vki_io_event));
sewardj45f4e7c2005-09-27 19:20:21 +00001111 r = *(struct vki_aio_ring **)ARG2;
1112 vg_assert(ML_(valid_client_addr)((Addr)r, size, tid, "io_setup"));
sewardje6d5e722005-06-10 10:27:55 +00001113
sewardj45f4e7c2005-09-27 19:20:21 +00001114 ML_(notify_aspacem_and_tool_of_mmap)( (Addr)r, size,
1115 VKI_PROT_READ | VKI_PROT_WRITE,
1116 VKI_MAP_ANONYMOUS, -1, 0 );
sewardje6d5e722005-06-10 10:27:55 +00001117
sewardj45f4e7c2005-09-27 19:20:21 +00001118 POST_MEM_WRITE( ARG2, sizeof(vki_aio_context_t) );
sewardje6d5e722005-06-10 10:27:55 +00001119}
1120
1121// Nb: This wrapper is "Special" because we need 'size' to do the unmap
1122// after the syscall. We must get 'size' from the aio_ring structure,
1123// before the syscall, while the aio_ring structure still exists. (And we
1124// know that we must look at the aio_ring structure because Tom inspected the
1125// kernel and glibc sources to see what they do, yuk.)
1126//
1127// XXX This segment can be implicitly unmapped when aio
1128// file-descriptors are closed...
1129PRE(sys_io_destroy)
sewardj45f4e7c2005-09-27 19:20:21 +00001130{
sewardje6d5e722005-06-10 10:27:55 +00001131 struct vki_aio_ring *r;
1132 SizeT size;
1133
1134 PRINT("sys_io_destroy ( %llu )", (ULong)ARG1);
1135 PRE_REG_READ1(long, "io_destroy", vki_aio_context_t, ctx);
1136
1137 // If we are going to seg fault (due to a bogus ARG1) do it as late as
1138 // possible...
sewardj45f4e7c2005-09-27 19:20:21 +00001139 r = (struct vki_aio_ring *)ARG1;
sewardje6d5e722005-06-10 10:27:55 +00001140 size = VG_PGROUNDUP(sizeof(struct vki_aio_ring) +
1141 r->nr*sizeof(struct vki_io_event));
1142
1143 SET_STATUS_from_SysRes( VG_(do_syscall1)(SYSNO, ARG1) );
1144
sewardj45f4e7c2005-09-27 19:20:21 +00001145 if (SUCCESS && RES == 0) {
1146 Bool d = VG_(am_notify_munmap)( ARG1, size );
sewardje6d5e722005-06-10 10:27:55 +00001147 VG_TRACK( die_mem_munmap, ARG1, size );
sewardj45f4e7c2005-09-27 19:20:21 +00001148 if (d)
1149 VG_(discard_translations)( (Addr64)ARG1, (ULong)size,
1150 "PRE(sys_io_destroy)" );
sewardje6d5e722005-06-10 10:27:55 +00001151 }
1152}
1153
1154PRE(sys_io_getevents)
1155{
1156 *flags |= SfMayBlock;
1157 PRINT("sys_io_getevents ( %llu, %lld, %lld, %p, %p )",
1158 (ULong)ARG1,(Long)ARG2,(Long)ARG3,ARG4,ARG5);
1159 PRE_REG_READ5(long, "io_getevents",
1160 vki_aio_context_t, ctx_id, long, min_nr, long, nr,
1161 struct io_event *, events,
1162 struct timespec *, timeout);
1163 if (ARG3 > 0)
1164 PRE_MEM_WRITE( "io_getevents(events)",
1165 ARG4, sizeof(struct vki_io_event)*ARG3 );
1166 if (ARG5 != 0)
1167 PRE_MEM_READ( "io_getevents(timeout)",
1168 ARG5, sizeof(struct vki_timespec));
1169}
1170POST(sys_io_getevents)
1171{
1172 Int i;
1173 vg_assert(SUCCESS);
1174 if (RES > 0) {
1175 POST_MEM_WRITE( ARG4, sizeof(struct vki_io_event)*RES );
1176 for (i = 0; i < RES; i++) {
1177 const struct vki_io_event *vev = ((struct vki_io_event *)ARG4) + i;
1178 const struct vki_iocb *cb = (struct vki_iocb *)(Addr)vev->obj;
1179
1180 switch (cb->aio_lio_opcode) {
1181 case VKI_IOCB_CMD_PREAD:
1182 if (vev->result > 0)
1183 POST_MEM_WRITE( cb->aio_buf, vev->result );
1184 break;
1185
1186 case VKI_IOCB_CMD_PWRITE:
1187 break;
1188
1189 default:
1190 VG_(message)(Vg_DebugMsg,
1191 "Warning: unhandled io_getevents opcode: %u\n",
1192 cb->aio_lio_opcode);
1193 break;
1194 }
1195 }
1196 }
1197}
1198
1199PRE(sys_io_submit)
1200{
1201 Int i;
1202
njn68e46592005-08-26 19:42:27 +00001203 PRINT("sys_io_submit ( %llu, %ld, %p )", (ULong)ARG1,ARG2,ARG3);
sewardje6d5e722005-06-10 10:27:55 +00001204 PRE_REG_READ3(long, "io_submit",
1205 vki_aio_context_t, ctx_id, long, nr,
1206 struct iocb **, iocbpp);
1207 PRE_MEM_READ( "io_submit(iocbpp)", ARG3, ARG2*sizeof(struct vki_iocb *) );
1208 if (ARG3 != 0) {
1209 for (i = 0; i < ARG2; i++) {
1210 struct vki_iocb *cb = ((struct vki_iocb **)ARG3)[i];
1211 PRE_MEM_READ( "io_submit(iocb)", (Addr)cb, sizeof(struct vki_iocb) );
1212 switch (cb->aio_lio_opcode) {
1213 case VKI_IOCB_CMD_PREAD:
1214 PRE_MEM_WRITE( "io_submit(PREAD)", cb->aio_buf, cb->aio_nbytes );
1215 break;
1216
1217 case VKI_IOCB_CMD_PWRITE:
1218 PRE_MEM_READ( "io_submit(PWRITE)", cb->aio_buf, cb->aio_nbytes );
1219 break;
1220
1221 default:
1222 VG_(message)(Vg_DebugMsg,"Warning: unhandled io_submit opcode: %u\n",
1223 cb->aio_lio_opcode);
1224 break;
1225 }
1226 }
1227 }
1228}
1229
1230PRE(sys_io_cancel)
1231{
toma1d56802005-07-25 15:28:36 +00001232 PRINT("sys_io_cancel ( %llu, %p, %p )", (ULong)ARG1,ARG2,ARG3);
sewardje6d5e722005-06-10 10:27:55 +00001233 PRE_REG_READ3(long, "io_cancel",
1234 vki_aio_context_t, ctx_id, struct iocb *, iocb,
1235 struct io_event *, result);
1236 PRE_MEM_READ( "io_cancel(iocb)", ARG2, sizeof(struct vki_iocb) );
1237 PRE_MEM_WRITE( "io_cancel(result)", ARG3, sizeof(struct vki_io_event) );
1238}
sewardje6d5e722005-06-10 10:27:55 +00001239POST(sys_io_cancel)
1240{
1241 POST_MEM_WRITE( ARG3, sizeof(struct vki_io_event) );
1242}
1243
njn73975482005-08-30 02:45:44 +00001244/* ---------------------------------------------------------------------
1245 *_mempolicy wrappers
1246 ------------------------------------------------------------------ */
1247
tom70a5cb02005-10-20 17:00:23 +00001248PRE(sys_mbind)
1249{
1250 PRINT("sys_mbind ( %p, %lu, %d, %p, %lu, %u )", ARG1,ARG2,ARG3,ARG4,ARG5,ARG6);
1251 PRE_REG_READ6(long, "mbind",
1252 unsigned long, start, unsigned long, len,
1253 unsigned long, policy, unsigned long *, nodemask,
1254 unsigned long, maxnode, unsigned, flags);
1255 if (ARG1 != 0)
1256 PRE_MEM_READ( "mbind(nodemask)", ARG4,
1257 VG_ROUNDUP( ARG5, sizeof(UWord) ) / sizeof(UWord) );
1258}
1259
tom2af58f22005-07-22 15:04:14 +00001260PRE(sys_set_mempolicy)
1261{
toma1d56802005-07-25 15:28:36 +00001262 PRINT("sys_set_mempolicy ( %d, %p, %d )", ARG1,ARG2,ARG3);
tom2af58f22005-07-22 15:04:14 +00001263 PRE_REG_READ3(long, "set_mempolicy",
1264 int, policy, unsigned long *, nodemask,
1265 unsigned long, maxnode);
1266 PRE_MEM_READ( "set_mempolicy(nodemask)", ARG2,
1267 VG_ROUNDUP( ARG3, sizeof(UWord) ) / sizeof(UWord) );
1268}
1269
1270PRE(sys_get_mempolicy)
1271{
toma1d56802005-07-25 15:28:36 +00001272 PRINT("sys_get_mempolicy ( %p, %p, %d, %p, %x )", ARG1,ARG2,ARG3,ARG4,ARG5);
tom2af58f22005-07-22 15:04:14 +00001273 PRE_REG_READ5(long, "get_mempolicy",
1274 int *, policy, unsigned long *, nodemask,
1275 unsigned long, maxnode, unsigned long, addr,
1276 unsigned long, flags);
1277 if (ARG1 != 0)
1278 PRE_MEM_WRITE( "get_mempolicy(policy)", ARG1, sizeof(Int) );
1279 if (ARG2 != 0)
1280 PRE_MEM_WRITE( "get_mempolicy(nodemask)", ARG2,
1281 VG_ROUNDUP( ARG3, sizeof(UWord) * 8 ) / sizeof(UWord) );
1282}
1283POST(sys_get_mempolicy)
1284{
1285 if (ARG1 != 0)
1286 POST_MEM_WRITE( ARG1, sizeof(Int) );
1287 if (ARG2 != 0)
1288 POST_MEM_WRITE( ARG2, VG_ROUNDUP( ARG3, sizeof(UWord) * 8 ) / sizeof(UWord) );
1289}
1290
njn73975482005-08-30 02:45:44 +00001291/* ---------------------------------------------------------------------
1292 inotify_* wrappers
1293 ------------------------------------------------------------------ */
1294
tom0bcaf2a2005-07-25 15:21:41 +00001295PRE(sys_inotify_init)
1296{
1297 PRINT("sys_inotify_init ( )");
1298 PRE_REG_READ0(long, "inotify_init");
1299}
1300POST(sys_inotify_init)
1301{
1302 vg_assert(SUCCESS);
1303 if (!ML_(fd_allowed)(RES, "inotify_init", tid, True)) {
1304 VG_(close)(RES);
1305 SET_STATUS_Failure( VKI_EMFILE );
1306 } else {
1307 if (VG_(clo_track_fds))
1308 ML_(record_fd_open_nameless) (tid, RES);
1309 }
1310}
1311
1312PRE(sys_inotify_add_watch)
1313{
toma1d56802005-07-25 15:28:36 +00001314 PRINT( "sys_inotify_add_watch ( %d, %p, %x )", ARG1,ARG2,ARG3);
tom0bcaf2a2005-07-25 15:21:41 +00001315 PRE_REG_READ3(long, "inotify_add_watch", int, fd, char *, path, int, mask);
1316 PRE_MEM_RASCIIZ( "inotify_add_watch(path)", ARG2 );
1317}
1318
1319PRE(sys_inotify_rm_watch)
1320{
toma1d56802005-07-25 15:28:36 +00001321 PRINT( "sys_inotify_rm_watch ( %d, %x )", ARG1,ARG2);
tom0bcaf2a2005-07-25 15:21:41 +00001322 PRE_REG_READ2(long, "inotify_rm_watch", int, fd, int, wd);
1323}
1324
njn73975482005-08-30 02:45:44 +00001325/* ---------------------------------------------------------------------
1326 mq_* wrappers
1327 ------------------------------------------------------------------ */
1328
njn4279a882005-08-26 03:43:28 +00001329PRE(sys_mq_open)
1330{
1331 PRINT("sys_mq_open( %p(%s), %d, %lld, %p )",
1332 ARG1,ARG1,ARG2,(ULong)ARG3,ARG4);
1333 PRE_REG_READ4(long, "mq_open",
1334 const char *, name, int, oflag, vki_mode_t, mode,
1335 struct mq_attr *, attr);
1336 PRE_MEM_RASCIIZ( "mq_open(name)", ARG1 );
1337 if ((ARG2 & VKI_O_CREAT) != 0 && ARG4 != 0) {
1338 const struct vki_mq_attr *attr = (struct vki_mq_attr *)ARG4;
1339 PRE_MEM_READ( "mq_open(attr->mq_maxmsg)",
1340 (Addr)&attr->mq_maxmsg, sizeof(attr->mq_maxmsg) );
1341 PRE_MEM_READ( "mq_open(attr->mq_msgsize)",
1342 (Addr)&attr->mq_msgsize, sizeof(attr->mq_msgsize) );
1343 }
1344}
njn4279a882005-08-26 03:43:28 +00001345POST(sys_mq_open)
1346{
1347 vg_assert(SUCCESS);
1348 if (!ML_(fd_allowed)(RES, "mq_open", tid, True)) {
1349 VG_(close)(RES);
1350 SET_STATUS_Failure( VKI_EMFILE );
1351 } else {
1352 if (VG_(clo_track_fds))
1353 ML_(record_fd_open_with_given_name)(tid, RES, (Char*)ARG1);
1354 }
1355}
1356
1357PRE(sys_mq_unlink)
1358{
1359 PRINT("sys_mq_unlink ( %p(%s) )", ARG1,ARG1);
1360 PRE_REG_READ1(long, "mq_unlink", const char *, name);
1361 PRE_MEM_RASCIIZ( "mq_unlink(name)", ARG1 );
1362}
1363
1364PRE(sys_mq_timedsend)
1365{
1366 *flags |= SfMayBlock;
1367 PRINT("sys_mq_timedsend ( %d, %p, %llu, %d, %p )",
1368 ARG1,ARG2,(ULong)ARG3,ARG4,ARG5);
1369 PRE_REG_READ5(long, "mq_timedsend",
1370 vki_mqd_t, mqdes, const char *, msg_ptr, vki_size_t, msg_len,
1371 unsigned int, msg_prio, const struct timespec *, abs_timeout);
1372 if (!ML_(fd_allowed)(ARG1, "mq_timedsend", tid, False)) {
1373 SET_STATUS_Failure( VKI_EBADF );
1374 } else {
1375 PRE_MEM_READ( "mq_timedsend(msg_ptr)", ARG2, ARG3 );
1376 if (ARG5 != 0)
1377 PRE_MEM_READ( "mq_timedsend(abs_timeout)", ARG5,
1378 sizeof(struct vki_timespec) );
1379 }
1380}
1381
1382PRE(sys_mq_timedreceive)
1383{
1384 *flags |= SfMayBlock;
1385 PRINT("sys_mq_timedreceive( %d, %p, %llu, %p, %p )",
1386 ARG1,ARG2,(ULong)ARG3,ARG4,ARG5);
1387 PRE_REG_READ5(ssize_t, "mq_timedreceive",
1388 vki_mqd_t, mqdes, char *, msg_ptr, vki_size_t, msg_len,
1389 unsigned int *, msg_prio,
1390 const struct timespec *, abs_timeout);
1391 if (!ML_(fd_allowed)(ARG1, "mq_timedreceive", tid, False)) {
1392 SET_STATUS_Failure( VKI_EBADF );
1393 } else {
1394 PRE_MEM_WRITE( "mq_timedreceive(msg_ptr)", ARG2, ARG3 );
1395 if (ARG4 != 0)
1396 PRE_MEM_WRITE( "mq_timedreceive(msg_prio)",
1397 ARG4, sizeof(unsigned int) );
1398 if (ARG5 != 0)
1399 PRE_MEM_READ( "mq_timedreceive(abs_timeout)",
1400 ARG5, sizeof(struct vki_timespec) );
1401 }
1402}
njn4279a882005-08-26 03:43:28 +00001403POST(sys_mq_timedreceive)
1404{
1405 POST_MEM_WRITE( ARG2, ARG3 );
1406 if (ARG4 != 0)
1407 POST_MEM_WRITE( ARG4, sizeof(unsigned int) );
1408}
1409
1410PRE(sys_mq_notify)
1411{
1412 PRINT("sys_mq_notify( %d, %p )", ARG1,ARG2 );
1413 PRE_REG_READ2(long, "mq_notify",
1414 vki_mqd_t, mqdes, const struct sigevent *, notification);
1415 if (!ML_(fd_allowed)(ARG1, "mq_notify", tid, False))
1416 SET_STATUS_Failure( VKI_EBADF );
1417 else if (ARG2 != 0)
1418 PRE_MEM_READ( "mq_notify(notification)",
1419 ARG2, sizeof(struct vki_sigevent) );
1420}
1421
1422PRE(sys_mq_getsetattr)
1423{
1424 PRINT("sys_mq_getsetattr( %d, %p, %p )", ARG1,ARG2,ARG3 );
1425 PRE_REG_READ3(long, "mq_getsetattr",
1426 vki_mqd_t, mqdes, const struct mq_attr *, mqstat,
1427 struct mq_attr *, omqstat);
1428 if (!ML_(fd_allowed)(ARG1, "mq_getsetattr", tid, False)) {
1429 SET_STATUS_Failure( VKI_EBADF );
1430 } else {
1431 if (ARG2 != 0) {
1432 const struct vki_mq_attr *attr = (struct vki_mq_attr *)ARG2;
1433 PRE_MEM_READ( "mq_getsetattr(mqstat->mq_flags)",
1434 (Addr)&attr->mq_flags, sizeof(attr->mq_flags) );
1435 }
1436 if (ARG3 != 0)
1437 PRE_MEM_WRITE( "mq_getsetattr(omqstat)", ARG3,
1438 sizeof(struct vki_mq_attr) );
1439 }
1440}
njn4279a882005-08-26 03:43:28 +00001441POST(sys_mq_getsetattr)
1442{
1443 if (ARG3 != 0)
1444 POST_MEM_WRITE( ARG3, sizeof(struct vki_mq_attr) );
1445}
1446
njn73975482005-08-30 02:45:44 +00001447/* ---------------------------------------------------------------------
1448 clock_* wrappers
1449 ------------------------------------------------------------------ */
1450
njn1588bc02005-08-26 03:49:43 +00001451PRE(sys_clock_settime)
1452{
1453 PRINT("sys_clock_settime( %d, %p )", ARG1,ARG2);
1454 PRE_REG_READ2(long, "clock_settime",
1455 vki_clockid_t, clk_id, const struct timespec *, tp);
1456 PRE_MEM_READ( "clock_settime(tp)", ARG2, sizeof(struct vki_timespec) );
1457}
1458
1459PRE(sys_clock_gettime)
1460{
1461 PRINT("sys_clock_gettime( %d, %p )" , ARG1,ARG2);
1462 PRE_REG_READ2(long, "clock_gettime",
1463 vki_clockid_t, clk_id, struct timespec *, tp);
1464 PRE_MEM_WRITE( "clock_gettime(tp)", ARG2, sizeof(struct vki_timespec) );
1465}
1466POST(sys_clock_gettime)
1467{
1468 POST_MEM_WRITE( ARG2, sizeof(struct vki_timespec) );
1469}
1470
1471PRE(sys_clock_getres)
1472{
1473 PRINT("sys_clock_getres( %d, %p )" , ARG1,ARG2);
1474 // Nb: we can't use "RES" as the param name because that's a macro
1475 // defined above!
1476 PRE_REG_READ2(long, "clock_getres",
1477 vki_clockid_t, clk_id, struct timespec *, res);
1478 if (ARG2 != 0)
1479 PRE_MEM_WRITE( "clock_getres(res)", ARG2, sizeof(struct vki_timespec) );
1480}
1481POST(sys_clock_getres)
1482{
1483 if (ARG2 != 0)
1484 POST_MEM_WRITE( ARG2, sizeof(struct vki_timespec) );
1485}
1486
1487PRE(sys_clock_nanosleep)
1488{
1489 *flags |= SfMayBlock|SfPostOnFail;
1490 PRINT("sys_clock_nanosleep( %d, %d, %p, %p )", ARG1,ARG2,ARG3,ARG4);
1491 PRE_REG_READ4(int32_t, "clock_nanosleep",
1492 vki_clockid_t, clkid, int, flags,
1493 const struct timespec *, rqtp, struct timespec *, rmtp);
1494 PRE_MEM_READ( "clock_nanosleep(rqtp)", ARG3, sizeof(struct vki_timespec) );
1495 if (ARG4 != 0)
1496 PRE_MEM_WRITE( "clock_nanosleep(rmtp)", ARG4, sizeof(struct vki_timespec) );
1497}
1498POST(sys_clock_nanosleep)
1499{
1500 if (ARG4 != 0 && FAILURE && RES_unchecked == VKI_EINTR)
1501 POST_MEM_WRITE( ARG4, sizeof(struct vki_timespec) );
1502}
1503
njn73975482005-08-30 02:45:44 +00001504/* ---------------------------------------------------------------------
1505 timer_* wrappers
1506 ------------------------------------------------------------------ */
1507
njn424c0562005-08-26 03:54:30 +00001508PRE(sys_timer_create)
1509{
1510 PRINT("sys_timer_create( %d, %p, %p )", ARG1,ARG2,ARG3);
1511 PRE_REG_READ3(long, "timer_create",
1512 vki_clockid_t, clockid, struct sigevent *, evp,
1513 vki_timer_t *, timerid);
1514 if (ARG2 != 0)
1515 PRE_MEM_READ( "timer_create(evp)", ARG2, sizeof(struct vki_sigevent) );
1516 PRE_MEM_WRITE( "timer_create(timerid)", ARG3, sizeof(vki_timer_t) );
1517}
1518POST(sys_timer_create)
1519{
1520 POST_MEM_WRITE( ARG3, sizeof(vki_timer_t) );
1521}
1522
1523PRE(sys_timer_settime)
1524{
1525 PRINT("sys_timer_settime( %lld, %d, %p, %p )", (ULong)ARG1,ARG2,ARG3,ARG4);
1526 PRE_REG_READ4(long, "timer_settime",
1527 vki_timer_t, timerid, int, flags,
1528 const struct itimerspec *, value,
1529 struct itimerspec *, ovalue);
1530 PRE_MEM_READ( "timer_settime(value)", ARG3,
1531 sizeof(struct vki_itimerspec) );
1532 if (ARG4 != 0)
1533 PRE_MEM_WRITE( "timer_settime(ovalue)", ARG4,
1534 sizeof(struct vki_itimerspec) );
1535}
1536POST(sys_timer_settime)
1537{
1538 if (ARG4 != 0)
1539 POST_MEM_WRITE( ARG4, sizeof(struct vki_itimerspec) );
1540}
1541
1542PRE(sys_timer_gettime)
1543{
1544 PRINT("sys_timer_gettime( %lld, %p )", (ULong)ARG1,ARG2);
1545 PRE_REG_READ2(long, "timer_gettime",
1546 vki_timer_t, timerid, struct itimerspec *, value);
1547 PRE_MEM_WRITE( "timer_gettime(value)", ARG2,
1548 sizeof(struct vki_itimerspec));
1549}
1550POST(sys_timer_gettime)
1551{
1552 POST_MEM_WRITE( ARG2, sizeof(struct vki_itimerspec) );
1553}
1554
1555PRE(sys_timer_getoverrun)
1556{
1557 PRINT("sys_timer_getoverrun( %p )", ARG1);
1558 PRE_REG_READ1(long, "timer_getoverrun", vki_timer_t, timerid);
1559}
1560
1561PRE(sys_timer_delete)
1562{
1563 PRINT("sys_timer_delete( %p )", ARG1);
1564 PRE_REG_READ1(long, "timer_delete", vki_timer_t, timerid);
1565}
1566
njn73975482005-08-30 02:45:44 +00001567/* ---------------------------------------------------------------------
1568 capabilities wrappers
1569 ------------------------------------------------------------------ */
1570
njn9fe7b122005-08-26 04:03:04 +00001571PRE(sys_capget)
1572{
1573 PRINT("sys_capget ( %p, %p )", ARG1, ARG2 );
1574 PRE_REG_READ2(long, "capget",
1575 vki_cap_user_header_t, header, vki_cap_user_data_t, data);
1576 PRE_MEM_READ( "capget(header)", ARG1,
1577 sizeof(struct __vki_user_cap_header_struct) );
1578 PRE_MEM_WRITE( "capget(data)", ARG2,
1579 sizeof(struct __vki_user_cap_data_struct) );
1580}
1581POST(sys_capget)
1582{
1583 if (ARG2 != (Addr)NULL)
1584 POST_MEM_WRITE( ARG2, sizeof(struct __vki_user_cap_data_struct) );
1585}
1586
1587PRE(sys_capset)
1588{
1589 PRINT("sys_capset ( %p, %p )", ARG1, ARG2 );
1590 PRE_REG_READ2(long, "capset",
1591 vki_cap_user_header_t, header,
1592 const vki_cap_user_data_t, data);
1593 PRE_MEM_READ( "capset(header)",
1594 ARG1, sizeof(struct __vki_user_cap_header_struct) );
1595 PRE_MEM_READ( "capset(data)",
1596 ARG2, sizeof(struct __vki_user_cap_data_struct) );
1597}
1598
njn73975482005-08-30 02:45:44 +00001599/* ---------------------------------------------------------------------
1600 16-bit uid/gid/groups wrappers
1601 ------------------------------------------------------------------ */
1602
njna3b67b72005-08-26 04:27:54 +00001603PRE(sys_getuid16)
1604{
1605 PRINT("sys_getuid16 ( )");
1606 PRE_REG_READ0(long, "getuid16");
1607}
1608
1609PRE(sys_setuid16)
1610{
1611 PRINT("sys_setuid16 ( %d )", ARG1);
1612 PRE_REG_READ1(long, "setuid16", vki_old_uid_t, uid);
1613}
1614
1615PRE(sys_getgid16)
1616{
1617 PRINT("sys_getgid16 ( )");
1618 PRE_REG_READ0(long, "getgid16");
1619}
1620
1621PRE(sys_setgid16)
1622{
1623 PRINT("sys_setgid16 ( %d )", ARG1);
1624 PRE_REG_READ1(long, "setgid16", vki_old_gid_t, gid);
1625}
1626
1627PRE(sys_geteuid16)
1628{
1629 PRINT("sys_geteuid16 ( )");
1630 PRE_REG_READ0(long, "geteuid16");
1631}
1632
1633PRE(sys_getegid16)
1634{
1635 PRINT("sys_getegid16 ( )");
1636 PRE_REG_READ0(long, "getegid16");
1637}
1638
1639PRE(sys_setreuid16)
1640{
1641 PRINT("setreuid16 ( 0x%x, 0x%x )", ARG1, ARG2);
1642 PRE_REG_READ2(long, "setreuid16", vki_old_uid_t, ruid, vki_old_uid_t, euid);
1643}
1644
1645PRE(sys_setregid16)
1646{
1647 PRINT("sys_setregid16 ( %d, %d )", ARG1, ARG2);
1648 PRE_REG_READ2(long, "setregid16", vki_old_gid_t, rgid, vki_old_gid_t, egid);
1649}
1650
1651PRE(sys_getgroups16)
1652{
1653 PRINT("sys_getgroups16 ( %d, %p )", ARG1, ARG2);
1654 PRE_REG_READ2(long, "getgroups16", int, size, vki_old_gid_t *, list);
1655 if (ARG1 > 0)
1656 PRE_MEM_WRITE( "getgroups16(list)", ARG2, ARG1 * sizeof(vki_old_gid_t) );
1657}
1658POST(sys_getgroups16)
1659{
1660 vg_assert(SUCCESS);
1661 if (ARG1 > 0 && RES > 0)
1662 POST_MEM_WRITE( ARG2, RES * sizeof(vki_old_gid_t) );
1663}
1664
1665PRE(sys_setgroups16)
1666{
1667 PRINT("sys_setgroups16 ( %llu, %p )", (ULong)ARG1, ARG2);
1668 PRE_REG_READ2(long, "setgroups16", int, size, vki_old_gid_t *, list);
1669 if (ARG1 > 0)
1670 PRE_MEM_READ( "setgroups16(list)", ARG2, ARG1 * sizeof(vki_old_gid_t) );
1671}
1672
njn73975482005-08-30 02:45:44 +00001673/* ---------------------------------------------------------------------
1674 *chown16 wrappers
1675 ------------------------------------------------------------------ */
1676
njnefc957c2005-08-26 04:36:10 +00001677PRE(sys_chown16)
1678{
1679 PRINT("sys_chown16 ( %p, 0x%x, 0x%x )", ARG1,ARG2,ARG3);
1680 PRE_REG_READ3(long, "chown16",
1681 const char *, path,
1682 vki_old_uid_t, owner, vki_old_gid_t, group);
1683 PRE_MEM_RASCIIZ( "chown16(path)", ARG1 );
1684}
1685
1686PRE(sys_fchown16)
1687{
1688 PRINT("sys_fchown16 ( %d, %d, %d )", ARG1,ARG2,ARG3);
1689 PRE_REG_READ3(long, "fchown16",
1690 unsigned int, fd, vki_old_uid_t, owner, vki_old_gid_t, group);
1691}
1692
njn73975482005-08-30 02:45:44 +00001693/* ---------------------------------------------------------------------
1694 *xattr wrappers
1695 ------------------------------------------------------------------ */
1696
njn65ccc502005-08-30 01:53:54 +00001697PRE(sys_setxattr)
1698{
1699 *flags |= SfMayBlock;
1700 PRINT("sys_setxattr ( %p, %p, %p, %llu, %d )",
1701 ARG1, ARG2, ARG3, (ULong)ARG4, ARG5);
1702 PRE_REG_READ5(long, "setxattr",
1703 char *, path, char *, name,
1704 void *, value, vki_size_t, size, int, flags);
1705 PRE_MEM_RASCIIZ( "setxattr(path)", ARG1 );
1706 PRE_MEM_RASCIIZ( "setxattr(name)", ARG2 );
1707 PRE_MEM_READ( "setxattr(value)", ARG3, ARG4 );
1708}
1709
1710PRE(sys_lsetxattr)
1711{
1712 *flags |= SfMayBlock;
1713 PRINT("sys_lsetxattr ( %p, %p, %p, %llu, %d )",
1714 ARG1, ARG2, ARG3, (ULong)ARG4, ARG5);
1715 PRE_REG_READ5(long, "lsetxattr",
1716 char *, path, char *, name,
1717 void *, value, vki_size_t, size, int, flags);
1718 PRE_MEM_RASCIIZ( "lsetxattr(path)", ARG1 );
1719 PRE_MEM_RASCIIZ( "lsetxattr(name)", ARG2 );
1720 PRE_MEM_READ( "lsetxattr(value)", ARG3, ARG4 );
1721}
1722
1723PRE(sys_fsetxattr)
1724{
1725 *flags |= SfMayBlock;
1726 PRINT("sys_fsetxattr ( %d, %p, %p, %llu, %d )",
1727 ARG1, ARG2, ARG3, (ULong)ARG4, ARG5);
1728 PRE_REG_READ5(long, "fsetxattr",
1729 int, fd, char *, name, void *, value,
1730 vki_size_t, size, int, flags);
1731 PRE_MEM_RASCIIZ( "fsetxattr(name)", ARG2 );
1732 PRE_MEM_READ( "fsetxattr(value)", ARG3, ARG4 );
1733}
1734
1735PRE(sys_getxattr)
1736{
1737 *flags |= SfMayBlock;
1738 PRINT("sys_getxattr ( %p, %p, %p, %llu )", ARG1,ARG2,ARG3, (ULong)ARG4);
1739 PRE_REG_READ4(ssize_t, "getxattr",
1740 char *, path, char *, name, void *, value, vki_size_t, size);
1741 PRE_MEM_RASCIIZ( "getxattr(path)", ARG1 );
1742 PRE_MEM_RASCIIZ( "getxattr(name)", ARG2 );
1743 PRE_MEM_WRITE( "getxattr(value)", ARG3, ARG4 );
1744}
1745POST(sys_getxattr)
1746{
1747 vg_assert(SUCCESS);
1748 if (RES > 0 && ARG3 != (Addr)NULL) {
1749 POST_MEM_WRITE( ARG3, RES );
1750 }
1751}
1752
1753PRE(sys_lgetxattr)
1754{
1755 *flags |= SfMayBlock;
1756 PRINT("sys_lgetxattr ( %p, %p, %p, %llu )", ARG1,ARG2,ARG3, (ULong)ARG4);
1757 PRE_REG_READ4(ssize_t, "lgetxattr",
1758 char *, path, char *, name, void *, value, vki_size_t, size);
1759 PRE_MEM_RASCIIZ( "lgetxattr(path)", ARG1 );
1760 PRE_MEM_RASCIIZ( "lgetxattr(name)", ARG2 );
1761 PRE_MEM_WRITE( "lgetxattr(value)", ARG3, ARG4 );
1762}
1763POST(sys_lgetxattr)
1764{
1765 vg_assert(SUCCESS);
1766 if (RES > 0 && ARG3 != (Addr)NULL) {
1767 POST_MEM_WRITE( ARG3, RES );
1768 }
1769}
1770
1771PRE(sys_fgetxattr)
1772{
1773 *flags |= SfMayBlock;
1774 PRINT("sys_fgetxattr ( %d, %p, %p, %llu )", ARG1, ARG2, ARG3, (ULong)ARG4);
1775 PRE_REG_READ4(ssize_t, "fgetxattr",
1776 int, fd, char *, name, void *, value, vki_size_t, size);
1777 PRE_MEM_RASCIIZ( "fgetxattr(name)", ARG2 );
1778 PRE_MEM_WRITE( "fgetxattr(value)", ARG3, ARG4 );
1779}
1780POST(sys_fgetxattr)
1781{
1782 if (RES > 0 && ARG3 != (Addr)NULL)
1783 POST_MEM_WRITE( ARG3, RES );
1784}
1785
1786PRE(sys_listxattr)
1787{
1788 *flags |= SfMayBlock;
1789 PRINT("sys_listxattr ( %p, %p, %llu )", ARG1, ARG2, (ULong)ARG3);
1790 PRE_REG_READ3(ssize_t, "listxattr",
1791 char *, path, char *, list, vki_size_t, size);
1792 PRE_MEM_RASCIIZ( "listxattr(path)", ARG1 );
1793 PRE_MEM_WRITE( "listxattr(list)", ARG2, ARG3 );
1794}
1795POST(sys_listxattr)
1796{
1797 if (RES > 0 && ARG2 != (Addr)NULL)
1798 POST_MEM_WRITE( ARG2, RES );
1799}
1800
1801PRE(sys_llistxattr)
1802{
1803 *flags |= SfMayBlock;
1804 PRINT("sys_llistxattr ( %p, %p, %llu )", ARG1, ARG2, (ULong)ARG3);
1805 PRE_REG_READ3(ssize_t, "llistxattr",
1806 char *, path, char *, list, vki_size_t, size);
1807 PRE_MEM_RASCIIZ( "llistxattr(path)", ARG1 );
1808 PRE_MEM_WRITE( "llistxattr(list)", ARG2, ARG3 );
1809}
1810POST(sys_llistxattr)
1811{
1812 if (RES > 0 && ARG2 != (Addr)NULL)
1813 POST_MEM_WRITE( ARG2, RES );
1814}
1815
1816PRE(sys_flistxattr)
1817{
1818 *flags |= SfMayBlock;
1819 PRINT("sys_flistxattr ( %d, %p, %llu )", ARG1, ARG2, (ULong)ARG3);
1820 PRE_REG_READ3(ssize_t, "flistxattr",
1821 int, fd, char *, list, vki_size_t, size);
1822 PRE_MEM_WRITE( "flistxattr(list)", ARG2, ARG3 );
1823}
1824POST(sys_flistxattr)
1825{
1826 if (RES > 0 && ARG2 != (Addr)NULL)
1827 POST_MEM_WRITE( ARG2, RES );
1828}
1829
1830PRE(sys_removexattr)
1831{
1832 *flags |= SfMayBlock;
1833 PRINT("sys_removexattr ( %p, %p )", ARG1, ARG2);
1834 PRE_REG_READ2(long, "removexattr", char *, path, char *, name);
1835 PRE_MEM_RASCIIZ( "removexattr(path)", ARG1 );
1836 PRE_MEM_RASCIIZ( "removexattr(name)", ARG2 );
1837}
1838
1839PRE(sys_lremovexattr)
1840{
1841 *flags |= SfMayBlock;
1842 PRINT("sys_lremovexattr ( %p, %p )", ARG1, ARG2);
1843 PRE_REG_READ2(long, "lremovexattr", char *, path, char *, name);
1844 PRE_MEM_RASCIIZ( "lremovexattr(path)", ARG1 );
1845 PRE_MEM_RASCIIZ( "lremovexattr(name)", ARG2 );
1846}
1847
1848PRE(sys_fremovexattr)
1849{
1850 *flags |= SfMayBlock;
1851 PRINT("sys_fremovexattr ( %d, %p )", ARG1, ARG2);
1852 PRE_REG_READ2(long, "fremovexattr", int, fd, char *, name);
1853 PRE_MEM_RASCIIZ( "fremovexattr(name)", ARG2 );
1854}
1855
njn73975482005-08-30 02:45:44 +00001856/* ---------------------------------------------------------------------
1857 sched_* wrappers
1858 ------------------------------------------------------------------ */
1859
njnb2480c92005-08-30 02:17:23 +00001860PRE(sys_sched_setparam)
1861{
1862 PRINT("sched_setparam ( %d, %p )", ARG1, ARG2 );
1863 PRE_REG_READ2(long, "sched_setparam",
1864 vki_pid_t, pid, struct sched_param *, p);
1865 PRE_MEM_READ( "sched_setparam(p)", ARG2, sizeof(struct vki_sched_param) );
1866}
1867POST(sys_sched_setparam)
1868{
1869 POST_MEM_WRITE( ARG2, sizeof(struct vki_sched_param) );
1870}
1871
1872PRE(sys_sched_getparam)
1873{
1874 PRINT("sched_getparam ( %d, %p )", ARG1, ARG2 );
1875 PRE_REG_READ2(long, "sched_getparam",
1876 vki_pid_t, pid, struct sched_param *, p);
1877 PRE_MEM_WRITE( "sched_getparam(p)", ARG2, sizeof(struct vki_sched_param) );
1878}
1879POST(sys_sched_getparam)
1880{
1881 POST_MEM_WRITE( ARG2, sizeof(struct vki_sched_param) );
1882}
1883
1884PRE(sys_sched_getscheduler)
1885{
1886 PRINT("sys_sched_getscheduler ( %d )", ARG1);
1887 PRE_REG_READ1(long, "sched_getscheduler", vki_pid_t, pid);
1888}
1889
1890PRE(sys_sched_setscheduler)
1891{
1892 PRINT("sys_sched_setscheduler ( %d, %d, %p )", ARG1,ARG2,ARG3);
1893 PRE_REG_READ3(long, "sched_setscheduler",
1894 vki_pid_t, pid, int, policy, struct sched_param *, p);
1895 if (ARG3 != 0)
1896 PRE_MEM_READ( "sched_setscheduler(p)",
1897 ARG3, sizeof(struct vki_sched_param));
1898}
1899
1900PRE(sys_sched_yield)
1901{
1902 *flags |= SfMayBlock;
1903 PRINT("sched_yield()");
1904 PRE_REG_READ0(long, "sys_sched_yield");
1905}
1906
1907PRE(sys_sched_get_priority_max)
1908{
1909 PRINT("sched_get_priority_max ( %d )", ARG1);
1910 PRE_REG_READ1(long, "sched_get_priority_max", int, policy);
1911}
1912
1913PRE(sys_sched_get_priority_min)
1914{
1915 PRINT("sched_get_priority_min ( %d )", ARG1);
1916 PRE_REG_READ1(long, "sched_get_priority_min", int, policy);
1917}
1918
1919PRE(sys_sched_setaffinity)
1920{
1921 PRINT("sched_setaffinity ( %d, %d, %p )", ARG1, ARG2, ARG3);
1922 PRE_REG_READ3(long, "sched_setaffinity",
1923 vki_pid_t, pid, unsigned int, len, unsigned long *, mask);
1924 PRE_MEM_READ( "sched_setaffinity(mask)", ARG3, ARG2);
1925}
1926
1927PRE(sys_sched_getaffinity)
1928{
1929 PRINT("sched_getaffinity ( %d, %d, %p )", ARG1, ARG2, ARG3);
1930 PRE_REG_READ3(long, "sched_getaffinity",
1931 vki_pid_t, pid, unsigned int, len, unsigned long *, mask);
1932 PRE_MEM_WRITE( "sched_getaffinity(mask)", ARG3, ARG2);
1933}
1934POST(sys_sched_getaffinity)
1935{
1936 POST_MEM_WRITE(ARG3, ARG2);
1937}
1938
njncd405ea2005-08-31 02:44:31 +00001939/* ---------------------------------------------------------------------
1940 miscellaneous wrappers
1941 ------------------------------------------------------------------ */
1942
1943PRE(sys_munlockall)
1944{
1945 *flags |= SfMayBlock;
1946 PRINT("sys_munlockall ( )");
1947 PRE_REG_READ0(long, "munlockall");
1948}
1949
njnf4ef1822005-09-24 19:42:41 +00001950// This has different signatures for different platforms.
1951//
1952// x86: int sys_pipe(unsigned long __user *fildes);
1953// AMD64: long sys_pipe(int *fildes);
1954// ppc32: int sys_pipe(int __user *fildes);
1955// ppc64: int sys_pipe(int __user *fildes);
1956//
1957// The type of the argument is most important, and it is an array of 32 bit
1958// values in all cases. (The return type differs across platforms, but it
1959// is not used.) So we use 'int' as its type. This fixed bug #113230 which
1960// was caused by using an array of 'unsigned long's, which didn't work on
1961// AMD64.
njncd405ea2005-08-31 02:44:31 +00001962PRE(sys_pipe)
1963{
1964 PRINT("sys_pipe ( %p )", ARG1);
njnf4ef1822005-09-24 19:42:41 +00001965 PRE_REG_READ1(int, "pipe", int *, filedes);
1966 PRE_MEM_WRITE( "pipe(filedes)", ARG1, 2*sizeof(int) );
njncd405ea2005-08-31 02:44:31 +00001967}
1968POST(sys_pipe)
1969{
1970 Int *p = (Int *)ARG1;
1971
1972 if (!ML_(fd_allowed)(p[0], "pipe", tid, True) ||
1973 !ML_(fd_allowed)(p[1], "pipe", tid, True)) {
1974 VG_(close)(p[0]);
1975 VG_(close)(p[1]);
1976 SET_STATUS_Failure( VKI_EMFILE );
1977 } else {
1978 POST_MEM_WRITE( ARG1, 2*sizeof(int) );
1979 if (VG_(clo_track_fds)) {
1980 ML_(record_fd_open_nameless)(tid, p[0]);
1981 ML_(record_fd_open_nameless)(tid, p[1]);
1982 }
1983 }
1984}
1985
1986PRE(sys_quotactl)
1987{
1988 PRINT("sys_quotactl (0x%x, %p, 0x%x, 0x%x )", ARG1,ARG2,ARG3, ARG4);
1989 PRE_REG_READ4(long, "quotactl",
1990 unsigned int, cmd, const char *, special, vki_qid_t, id,
1991 void *, addr);
1992 PRE_MEM_RASCIIZ( "quotactl(special)", ARG2 );
1993}
1994
1995PRE(sys_waitid)
1996{
1997 *flags |= SfMayBlock;
1998 PRINT("sys_waitid( %d, %d, %p, %d, %p )", ARG1,ARG2,ARG3,ARG4,ARG5);
1999 PRE_REG_READ5(int32_t, "sys_waitid",
2000 int, which, vki_pid_t, pid, struct vki_siginfo *, infop,
2001 int, options, struct vki_rusage *, ru);
2002 PRE_MEM_WRITE( "waitid(infop)", ARG3, sizeof(struct vki_siginfo) );
2003 if (ARG5 != 0)
2004 PRE_MEM_WRITE( "waitid(ru)", ARG5, sizeof(struct vki_rusage) );
2005}
2006POST(sys_waitid)
2007{
2008 POST_MEM_WRITE( ARG3, sizeof(struct vki_siginfo) );
2009 if (ARG5 != 0)
2010 POST_MEM_WRITE( ARG5, sizeof(struct vki_rusage) );
2011}
2012
2013/* ---------------------------------------------------------------------
2014 utime wrapper
2015 ------------------------------------------------------------------ */
2016
2017PRE(sys_utime)
2018{
2019 *flags |= SfMayBlock;
2020 PRINT("sys_utime ( %p, %p )", ARG1,ARG2);
2021 PRE_REG_READ2(long, "utime", char *, filename, struct utimbuf *, buf);
2022 PRE_MEM_RASCIIZ( "utime(filename)", ARG1 );
2023 if (ARG2 != 0)
2024 PRE_MEM_READ( "utime(buf)", ARG2, sizeof(struct vki_utimbuf) );
2025}
2026
2027/* ---------------------------------------------------------------------
2028 lseek wrapper
2029 ------------------------------------------------------------------ */
2030
2031PRE(sys_lseek)
2032{
2033 PRINT("sys_lseek ( %d, %d, %d )", ARG1,ARG2,ARG3);
2034 PRE_REG_READ3(vki_off_t, "lseek",
2035 unsigned int, fd, vki_off_t, offset, unsigned int, whence);
2036}
2037
2038/* ---------------------------------------------------------------------
2039 sig* wrappers
2040 ------------------------------------------------------------------ */
2041
2042PRE(sys_sigpending)
2043{
2044 PRINT( "sys_sigpending ( %p )", ARG1 );
2045 PRE_REG_READ1(long, "sigpending", vki_old_sigset_t *, set);
2046 PRE_MEM_WRITE( "sigpending(set)", ARG1, sizeof(vki_old_sigset_t));
2047}
2048POST(sys_sigpending)
2049{
2050 POST_MEM_WRITE( ARG1, sizeof(vki_old_sigset_t) ) ;
2051}
2052
2053// This syscall is not used on amd64/Linux -- it only provides
2054// sys_rt_sigprocmask, which uses sigset_t rather than old_sigset_t.
2055// This wrapper is only suitable for 32-bit architectures.
2056// (XXX: so how is it that PRE(sys_sigpending) above doesn't need
2057// conditional compilation like this?)
2058#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
2059PRE(sys_sigprocmask)
2060{
2061 vki_old_sigset_t* set;
2062 vki_old_sigset_t* oldset;
2063 vki_sigset_t bigger_set;
2064 vki_sigset_t bigger_oldset;
2065
2066 PRINT("sys_sigprocmask ( %d, %p, %p )",ARG1,ARG2,ARG3);
2067 PRE_REG_READ3(long, "sigprocmask",
2068 int, how, vki_old_sigset_t *, set, vki_old_sigset_t *, oldset);
2069 if (ARG2 != 0)
2070 PRE_MEM_READ( "sigprocmask(set)", ARG2, sizeof(vki_old_sigset_t));
2071 if (ARG3 != 0)
2072 PRE_MEM_WRITE( "sigprocmask(oldset)", ARG3, sizeof(vki_old_sigset_t));
2073
2074 // Nb: We must convert the smaller vki_old_sigset_t params into bigger
2075 // vki_sigset_t params.
2076 set = (vki_old_sigset_t*)ARG2;
2077 oldset = (vki_old_sigset_t*)ARG3;
2078
2079 VG_(memset)(&bigger_set, 0, sizeof(vki_sigset_t));
2080 VG_(memset)(&bigger_oldset, 0, sizeof(vki_sigset_t));
2081 if (set)
2082 bigger_set.sig[0] = *(vki_old_sigset_t*)set;
2083
2084 SET_STATUS_from_SysRes(
2085 VG_(do_sys_sigprocmask) ( tid, ARG1 /*how*/,
2086 set ? &bigger_set : NULL,
2087 oldset ? &bigger_oldset : NULL)
2088 );
2089
2090 if (oldset)
2091 *oldset = bigger_oldset.sig[0];
2092
2093 if (SUCCESS)
2094 *flags |= SfPollAfter;
2095}
2096POST(sys_sigprocmask)
2097{
2098 vg_assert(SUCCESS);
2099 if (RES == 0 && ARG3 != 0)
2100 POST_MEM_WRITE( ARG3, sizeof(vki_old_sigset_t));
2101}
2102#endif
2103
2104/* ---------------------------------------------------------------------
2105 rt_sig* wrappers
2106 ------------------------------------------------------------------ */
2107
2108PRE(sys_rt_sigaction)
2109{
2110 PRINT("sys_rt_sigaction ( %d, %p, %p, %d )", ARG1,ARG2,ARG3,ARG4);
2111 PRE_REG_READ4(long, "rt_sigaction",
2112 int, signum, const struct sigaction *, act,
2113 struct sigaction *, oldact, vki_size_t, sigsetsize);
2114
2115 if (ARG2 != 0) {
2116 struct vki_sigaction *sa = (struct vki_sigaction *)ARG2;
2117 PRE_MEM_READ( "rt_sigaction(act->sa_handler)", (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler));
2118 PRE_MEM_READ( "rt_sigaction(act->sa_mask)", (Addr)&sa->sa_mask, sizeof(sa->sa_mask));
2119 PRE_MEM_READ( "rt_sigaction(act->sa_flags)", (Addr)&sa->sa_flags, sizeof(sa->sa_flags));
2120 if (sa->sa_flags & VKI_SA_RESTORER)
2121 PRE_MEM_READ( "rt_sigaction(act->sa_restorer)", (Addr)&sa->sa_restorer, sizeof(sa->sa_restorer));
2122 }
2123 if (ARG3 != 0)
2124 PRE_MEM_WRITE( "rt_sigaction(oldact)", ARG3, sizeof(struct vki_sigaction));
2125
2126 // XXX: doesn't seem right to be calling do_sys_sigaction for
2127 // sys_rt_sigaction... perhaps this function should be renamed
2128 // VG_(do_sys_rt_sigaction)() --njn
2129
2130 SET_STATUS_from_SysRes(
2131 VG_(do_sys_sigaction)(ARG1, (const struct vki_sigaction *)ARG2,
2132 (struct vki_sigaction *)ARG3)
2133 );
2134}
2135POST(sys_rt_sigaction)
2136{
2137 vg_assert(SUCCESS);
2138 if (RES == 0 && ARG3 != 0)
2139 POST_MEM_WRITE( ARG3, sizeof(struct vki_sigaction));
2140}
2141
2142PRE(sys_rt_sigprocmask)
2143{
2144 PRINT("sys_rt_sigprocmask ( %d, %p, %p, %llu )",ARG1,ARG2,ARG3,(ULong)ARG4);
2145 PRE_REG_READ4(long, "rt_sigprocmask",
2146 int, how, vki_sigset_t *, set, vki_sigset_t *, oldset,
2147 vki_size_t, sigsetsize);
2148 if (ARG2 != 0)
2149 PRE_MEM_READ( "rt_sigprocmask(set)", ARG2, sizeof(vki_sigset_t));
2150 if (ARG3 != 0)
2151 PRE_MEM_WRITE( "rt_sigprocmask(oldset)", ARG3, sizeof(vki_sigset_t));
2152
2153 // Like the kernel, we fail if the sigsetsize is not exactly what we expect.
2154 if (sizeof(vki_sigset_t) != ARG4)
2155 SET_STATUS_Failure( VKI_EMFILE );
2156 else {
2157 SET_STATUS_from_SysRes(
2158 VG_(do_sys_sigprocmask) ( tid, ARG1 /*how*/,
2159 (vki_sigset_t*) ARG2,
2160 (vki_sigset_t*) ARG3 )
2161 );
2162 }
2163
2164 if (SUCCESS)
2165 *flags |= SfPollAfter;
2166}
2167POST(sys_rt_sigprocmask)
2168{
2169 vg_assert(SUCCESS);
2170 if (RES == 0 && ARG3 != 0)
2171 POST_MEM_WRITE( ARG3, sizeof(vki_sigset_t));
2172}
2173
2174PRE(sys_rt_sigpending)
2175{
2176 PRINT( "sys_rt_sigpending ( %p )", ARG1 );
2177 PRE_REG_READ2(long, "rt_sigpending",
2178 vki_sigset_t *, set, vki_size_t, sigsetsize);
2179 PRE_MEM_WRITE( "rt_sigpending(set)", ARG1, sizeof(vki_sigset_t));
2180}
2181POST(sys_rt_sigpending)
2182{
2183 POST_MEM_WRITE( ARG1, sizeof(vki_sigset_t) ) ;
2184}
2185
2186PRE(sys_rt_sigtimedwait)
2187{
2188 *flags |= SfMayBlock;
2189 PRINT("sys_rt_sigtimedwait ( %p, %p, %p, %lld )",
2190 ARG1,ARG2,ARG3,(ULong)ARG4);
2191 PRE_REG_READ4(long, "rt_sigtimedwait",
2192 const vki_sigset_t *, set, vki_siginfo_t *, info,
2193 const struct timespec *, timeout, vki_size_t, sigsetsize);
2194 if (ARG1 != 0)
2195 PRE_MEM_READ( "rt_sigtimedwait(set)", ARG1, sizeof(vki_sigset_t));
2196 if (ARG2 != 0)
2197 PRE_MEM_WRITE( "rt_sigtimedwait(info)", ARG2, sizeof(vki_siginfo_t) );
2198 if (ARG3 != 0)
2199 PRE_MEM_READ( "rt_sigtimedwait(timeout)",
2200 ARG3, sizeof(struct vki_timespec) );
2201}
2202POST(sys_rt_sigtimedwait)
2203{
2204 if (ARG2 != 0)
2205 POST_MEM_WRITE( ARG2, sizeof(vki_siginfo_t) );
2206}
2207
2208PRE(sys_rt_sigqueueinfo)
2209{
2210 PRINT("sys_rt_sigqueueinfo(%d, %d, %p)", ARG1, ARG2, ARG3);
2211 PRE_REG_READ3(long, "rt_sigqueueinfo",
2212 int, pid, int, sig, vki_siginfo_t *, uinfo);
2213 if (ARG2 != 0)
2214 PRE_MEM_READ( "rt_sigqueueinfo(uinfo)", ARG3, sizeof(vki_siginfo_t) );
2215}
2216POST(sys_rt_sigqueueinfo)
2217{
2218 if (!ML_(client_signal_OK)(ARG2))
2219 SET_STATUS_Failure( VKI_EINVAL );
2220}
2221
2222// XXX: x86-specific? The kernel prototypes for the different archs are
2223// hard to decipher.
2224PRE(sys_rt_sigsuspend)
2225{
2226 /* The C library interface to sigsuspend just takes a pointer to
2227 a signal mask but this system call has two arguments - a pointer
2228 to the mask and the number of bytes used by it. The kernel insists
2229 on the size being equal to sizeof(sigset_t) however and will just
2230 return EINVAL if it isn't.
2231 */
2232 *flags |= SfMayBlock;
2233 PRINT("sys_rt_sigsuspend ( %p, %d )", ARG1,ARG2 );
2234 PRE_REG_READ2(int, "rt_sigsuspend", vki_sigset_t *, mask, vki_size_t, size)
2235 if (ARG1 != (Addr)NULL) {
2236 PRE_MEM_READ( "rt_sigsuspend(mask)", ARG1, sizeof(vki_sigset_t) );
2237 }
2238}
2239
2240/* ---------------------------------------------------------------------
2241 linux msg* wrapper helpers
2242 ------------------------------------------------------------------ */
2243
2244void
2245ML_(linux_PRE_sys_msgsnd) ( ThreadId tid,
2246 UWord arg0, UWord arg1, UWord arg2, UWord arg3 )
2247{
2248 /* int msgsnd(int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg); */
2249 struct vki_msgbuf *msgp = (struct vki_msgbuf *)arg1;
2250 PRE_MEM_READ( "msgsnd(msgp->mtype)", (Addr)&msgp->mtype, sizeof(msgp->mtype) );
2251 PRE_MEM_READ( "msgsnd(msgp->mtext)", (Addr)&msgp->mtext, arg2 );
2252}
2253
2254void
2255ML_(linux_PRE_sys_msgrcv) ( ThreadId tid,
2256 UWord arg0, UWord arg1, UWord arg2,
2257 UWord arg3, UWord arg4 )
2258{
2259 /* ssize_t msgrcv(int msqid, struct msgbuf *msgp, size_t msgsz,
2260 long msgtyp, int msgflg); */
2261 struct vki_msgbuf *msgp = (struct vki_msgbuf *)arg1;
2262 PRE_MEM_WRITE( "msgrcv(msgp->mtype)", (Addr)&msgp->mtype, sizeof(msgp->mtype) );
2263 PRE_MEM_WRITE( "msgrcv(msgp->mtext)", (Addr)&msgp->mtext, arg2 );
2264}
2265void
2266ML_(linux_POST_sys_msgrcv) ( ThreadId tid,
2267 UWord res,
2268 UWord arg0, UWord arg1, UWord arg2,
2269 UWord arg3, UWord arg4 )
2270{
2271 struct vki_msgbuf *msgp = (struct vki_msgbuf *)arg1;
2272 POST_MEM_WRITE( (Addr)&msgp->mtype, sizeof(msgp->mtype) );
2273 POST_MEM_WRITE( (Addr)&msgp->mtext, res );
2274}
2275
2276void
2277ML_(linux_PRE_sys_msgctl) ( ThreadId tid,
2278 UWord arg0, UWord arg1, UWord arg2 )
2279{
2280 /* int msgctl(int msqid, int cmd, struct msqid_ds *buf); */
2281 switch (arg1 /* cmd */) {
2282 case VKI_IPC_INFO:
2283 case VKI_MSG_INFO:
2284 case VKI_IPC_INFO|VKI_IPC_64:
2285 case VKI_MSG_INFO|VKI_IPC_64:
2286 PRE_MEM_WRITE( "msgctl(IPC_INFO, buf)",
2287 arg2, sizeof(struct vki_msginfo) );
2288 break;
2289 case VKI_IPC_STAT:
2290 case VKI_MSG_STAT:
2291 PRE_MEM_WRITE( "msgctl(IPC_STAT, buf)",
2292 arg2, sizeof(struct vki_msqid_ds) );
2293 break;
2294 case VKI_IPC_STAT|VKI_IPC_64:
2295 case VKI_MSG_STAT|VKI_IPC_64:
2296 PRE_MEM_WRITE( "msgctl(IPC_STAT, arg.buf)",
2297 arg2, sizeof(struct vki_msqid64_ds) );
2298 break;
2299 case VKI_IPC_SET:
2300 PRE_MEM_READ( "msgctl(IPC_SET, arg.buf)",
2301 arg2, sizeof(struct vki_msqid_ds) );
2302 break;
2303 case VKI_IPC_SET|VKI_IPC_64:
2304 PRE_MEM_READ( "msgctl(IPC_SET, arg.buf)",
2305 arg2, sizeof(struct vki_msqid64_ds) );
2306 break;
2307 }
2308}
2309void
2310ML_(linux_POST_sys_msgctl) ( ThreadId tid,
2311 UWord res,
2312 UWord arg0, UWord arg1, UWord arg2 )
2313{
2314 switch (arg1 /* cmd */) {
2315 case VKI_IPC_INFO:
2316 case VKI_MSG_INFO:
2317 case VKI_IPC_INFO|VKI_IPC_64:
2318 case VKI_MSG_INFO|VKI_IPC_64:
2319 POST_MEM_WRITE( arg2, sizeof(struct vki_msginfo) );
2320 break;
2321 case VKI_IPC_STAT:
2322 case VKI_MSG_STAT:
2323 POST_MEM_WRITE( arg2, sizeof(struct vki_msqid_ds) );
2324 break;
2325 case VKI_IPC_STAT|VKI_IPC_64:
2326 case VKI_MSG_STAT|VKI_IPC_64:
2327 POST_MEM_WRITE( arg2, sizeof(struct vki_msqid64_ds) );
2328 break;
2329 }
2330}
2331
tom363ec762006-03-21 10:58:35 +00002332/* ---------------------------------------------------------------------
2333 *at wrappers
2334 ------------------------------------------------------------------ */
2335
2336PRE(sys_openat)
2337{
2338 HChar name[30];
2339 SysRes sres;
2340
2341 if (ARG3 & VKI_O_CREAT) {
2342 // 4-arg version
2343 PRINT("sys_openat ( %d, %p(%s), %d, %d )",ARG1,ARG2,ARG2,ARG3,ARG4);
2344 PRE_REG_READ4(long, "openat",
2345 int, dfd, const char *, filename, int, flags, int, mode);
2346 } else {
2347 // 3-arg version
2348 PRINT("sys_openat ( %d, %p(%s), %d )",ARG1,ARG2,ARG2,ARG3);
2349 PRE_REG_READ3(long, "openat",
2350 int, dfd, const char *, filename, int, flags);
2351 }
2352
2353 if (!ML_(fd_allowed)(ARG1, "openat", tid, False))
2354 SET_STATUS_Failure( VKI_EBADF );
2355 else
2356 PRE_MEM_RASCIIZ( "openat(filename)", ARG2 );
2357
2358 /* Handle the case where the open is of /proc/self/cmdline or
2359 /proc/<pid>/cmdline, and just give it a copy of the fd for the
2360 fake file we cooked up at startup (in m_main). Also, seek the
2361 cloned fd back to the start. */
2362
2363 VG_(sprintf)(name, "/proc/%d/cmdline", VG_(getpid)());
2364 if (ML_(safe_to_deref)( (void*)ARG2, 1 )
2365 && (VG_(strcmp)((Char *)ARG2, name) == 0
2366 || VG_(strcmp)((Char *)ARG2, "/proc/self/cmdline") == 0)) {
2367 sres = VG_(dup)( VG_(cl_cmdline_fd) );
2368 SET_STATUS_from_SysRes( sres );
2369 if (!sres.isError) {
2370 OffT off = VG_(lseek)( sres.val, 0, VKI_SEEK_SET );
2371 if (off < 0)
2372 SET_STATUS_Failure( VKI_EMFILE );
2373 }
2374 return;
2375 }
2376
2377 /* Otherwise handle normally */
2378 *flags |= SfMayBlock;
2379}
2380
2381POST(sys_openat)
2382{
2383 vg_assert(SUCCESS);
2384 if (!ML_(fd_allowed)(RES, "openat", tid, True)) {
2385 VG_(close)(RES);
2386 SET_STATUS_Failure( VKI_EMFILE );
2387 } else {
2388 if (VG_(clo_track_fds))
2389 ML_(record_fd_open_with_given_name)(tid, RES, (Char*)ARG2);
2390 }
2391}
2392
2393PRE(sys_mkdirat)
2394{
2395 *flags |= SfMayBlock;
2396 PRINT("sys_mkdirat ( %d, %p(%s), %d )", ARG1,ARG2,ARG2,ARG3);
2397 PRE_REG_READ3(long, "mkdirat",
2398 int, dfd, const char *, pathname, int, mode);
2399 PRE_MEM_RASCIIZ( "mkdirat(pathname)", ARG2 );
2400}
2401
2402PRE(sys_mknodat)
2403{
2404 PRINT("sys_mknodat ( %d, %p(%s), 0x%x, 0x%x )", ARG1,ARG2,ARG2,ARG3,ARG4 );
2405 PRE_REG_READ4(long, "mknodat",
2406 int, dfd, const char *, pathname, int, mode, unsigned, dev);
2407 PRE_MEM_RASCIIZ( "mknodat(pathname)", ARG2 );
2408}
2409
2410PRE(sys_fchownat)
2411{
2412 PRINT("sys_fchownat ( %d, %p(%s), 0x%x, 0x%x )", ARG1,ARG2,ARG2,ARG3,ARG4);
2413 PRE_REG_READ4(long, "fchownat",
2414 int, dfd, const char *, path,
2415 vki_uid_t, owner, vki_gid_t, group);
2416 PRE_MEM_RASCIIZ( "fchownat(path)", ARG2 );
2417}
2418
2419PRE(sys_futimesat)
2420{
2421 PRINT("sys_futimesat ( %d, %p(%s), %p )", ARG1,ARG2,ARG2,ARG3);
2422 PRE_REG_READ3(long, "futimesat",
2423 int, dfd, char *, filename, struct timeval *, tvp);
2424 PRE_MEM_RASCIIZ( "futimesat(filename)", ARG2 );
2425 if (ARG3 != 0)
2426 PRE_MEM_READ( "futimesat(tvp)", ARG3, sizeof(struct vki_timeval) );
2427}
2428
2429PRE(sys_newfstatat)
2430{
2431 PRINT("sys_newfstatat ( %d, %p(%s), %p )", ARG1,ARG2,ARG2,ARG3);
2432 PRE_REG_READ3(long, "fstatat",
2433 int, dfd, char *, file_name, struct stat *, buf);
2434 PRE_MEM_RASCIIZ( "fstatat(file_name)", ARG2 );
2435 PRE_MEM_WRITE( "fstatat(buf)", ARG3, sizeof(struct vki_stat) );
2436}
2437
2438POST(sys_newfstatat)
2439{
2440 POST_MEM_WRITE( ARG3, sizeof(struct vki_stat) );
2441}
2442
2443PRE(sys_unlinkat)
2444{
2445 *flags |= SfMayBlock;
2446 PRINT("sys_unlinkat ( %d, %p(%s) )", ARG1,ARG2,ARG2);
2447 PRE_REG_READ2(long, "unlinkat", int, dfd, const char *, pathname);
2448 PRE_MEM_RASCIIZ( "unlinkat(pathname)", ARG2 );
2449}
2450
2451PRE(sys_renameat)
2452{
toma43717f2006-05-08 11:19:47 +00002453 PRINT("sys_renameat ( %d, %p(%s), %d, %p(%s) )", ARG1,ARG2,ARG2,ARG3,ARG4,ARG4);
2454 PRE_REG_READ4(long, "renameat",
2455 int, olddfd, const char *, oldpath,
2456 int, newdfd, const char *, newpath);
tom363ec762006-03-21 10:58:35 +00002457 PRE_MEM_RASCIIZ( "renameat(oldpath)", ARG2 );
toma43717f2006-05-08 11:19:47 +00002458 PRE_MEM_RASCIIZ( "renameat(newpath)", ARG4 );
tom363ec762006-03-21 10:58:35 +00002459}
2460
2461PRE(sys_linkat)
2462{
2463 *flags |= SfMayBlock;
toma43717f2006-05-08 11:19:47 +00002464 PRINT("sys_linkat ( %d, %p(%s), %d, %p(%s), %d )",ARG1,ARG2,ARG2,ARG3,ARG4,ARG4,ARG5);
2465 PRE_REG_READ5(long, "linkat",
2466 int, olddfd, const char *, oldpath,
2467 int, newdfd, const char *, newpath,
2468 int, flags);
tom363ec762006-03-21 10:58:35 +00002469 PRE_MEM_RASCIIZ( "linkat(oldpath)", ARG2);
toma43717f2006-05-08 11:19:47 +00002470 PRE_MEM_RASCIIZ( "linkat(newpath)", ARG4);
tom363ec762006-03-21 10:58:35 +00002471}
2472
2473PRE(sys_symlinkat)
2474{
2475 *flags |= SfMayBlock;
toma43717f2006-05-08 11:19:47 +00002476 PRINT("sys_symlinkat ( %p(%s), %d, %p(%s) )",ARG1,ARG1,ARG2,ARG3,ARG3);
tom363ec762006-03-21 10:58:35 +00002477 PRE_REG_READ3(long, "symlinkat",
toma43717f2006-05-08 11:19:47 +00002478 const char *, oldpath, int, newdfd, const char *, newpath);
2479 PRE_MEM_RASCIIZ( "symlinkat(oldpath)", ARG1 );
tom363ec762006-03-21 10:58:35 +00002480 PRE_MEM_RASCIIZ( "symlinkat(newpath)", ARG3 );
2481}
2482
2483PRE(sys_readlinkat)
2484{
2485 HChar name[25];
2486 Word saved = SYSNO;
2487
2488 PRINT("sys_readlinkat ( %d, %p(%s), %p, %llu )", ARG1,ARG2,ARG2,ARG3,(ULong)ARG4);
2489 PRE_REG_READ4(long, "readlinkat",
2490 int, dfd, const char *, path, char *, buf, int, bufsiz);
2491 PRE_MEM_RASCIIZ( "readlinkat(path)", ARG2 );
2492 PRE_MEM_WRITE( "readlinkat(buf)", ARG3,ARG4 );
2493
2494 /*
2495 * Handle the case where readlinkat is looking at /proc/self/exe or
2496 * /proc/<pid>/exe.
2497 */
2498 VG_(sprintf)(name, "/proc/%d/exe", VG_(getpid)());
2499 if (ML_(safe_to_deref)((void*)ARG2, 1)
2500 && (VG_(strcmp)((Char *)ARG2, name) == 0
2501 || VG_(strcmp)((Char *)ARG2, "/proc/self/exe") == 0)) {
2502 VG_(sprintf)(name, "/proc/self/fd/%d", VG_(cl_exec_fd));
2503 SET_STATUS_from_SysRes( VG_(do_syscall4)(saved, ARG1, (UWord)name,
2504 ARG3, ARG4));
2505 } else {
2506 /* Normal case */
2507 SET_STATUS_from_SysRes( VG_(do_syscall4)(saved, ARG1, ARG2, ARG3, ARG4));
2508 }
2509
2510 if (SUCCESS && RES > 0)
2511 POST_MEM_WRITE( ARG3, RES );
2512}
2513
2514PRE(sys_fchmodat)
2515{
2516 PRINT("sys_fchmodat ( %d, %p(%s), %d )", ARG1,ARG2,ARG2,ARG3);
2517 PRE_REG_READ3(long, "fchmodat",
2518 int, dfd, const char *, path, vki_mode_t, mode);
2519 PRE_MEM_RASCIIZ( "fchmodat(path)", ARG2 );
2520}
2521
2522PRE(sys_faccessat)
2523{
2524 PRINT("sys_faccessat ( %d, %p(%s), %d )", ARG1,ARG2,ARG2,ARG3);
2525 PRE_REG_READ3(long, "faccessat",
2526 int, dfd, const char *, pathname, int, mode);
2527 PRE_MEM_RASCIIZ( "faccessat(pathname)", ARG2 );
2528}
2529
sewardje6d5e722005-06-10 10:27:55 +00002530#undef PRE
2531#undef POST
nethercotefd453532004-11-17 17:21:12 +00002532
2533/*--------------------------------------------------------------------*/
2534/*--- end ---*/
2535/*--------------------------------------------------------------------*/