blob: 25fbe37c0d228fa9d221f19c0e4464f100b83a75 [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
njn87ef6a62003-08-14 15:23:55 +00003/*--- Handle system calls. vg_syscalls.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnc9539842002-10-02 13:26:35 +00007 This file is part of Valgrind, an extensible x86 protected-mode
8 emulator for monitoring program execution on x86-Unixes.
sewardjde4a1d02002-03-22 01:27:54 +00009
nethercotebb1c9912004-01-04 16:43:23 +000010 Copyright (C) 2000-2004 Julian Seward
sewardjde4a1d02002-03-22 01:27:54 +000011 jseward@acm.org
sewardjde4a1d02002-03-22 01:27:54 +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
njn25e49d8e72002-09-23 09:36:25 +000028 The GNU General Public License is contained in the file COPYING.
sewardjde4a1d02002-03-22 01:27:54 +000029*/
30
nethercotef1e5e152004-09-01 23:58:16 +000031#include "core.h"
sewardjde4a1d02002-03-22 01:27:54 +000032
33/* vg_unsafe.h should NOT be included into any file except this
34 one. */
35#include "vg_unsafe.h"
36
37
njn25e49d8e72002-09-23 09:36:25 +000038/* All system calls are channelled through here, doing two things:
sewardjde4a1d02002-03-22 01:27:54 +000039
nethercote996901a2004-08-03 13:29:09 +000040 * notify the tool of the memory events (reads, writes) happening
sewardjde4a1d02002-03-22 01:27:54 +000041
42 * perform the syscall, usually by passing it along to the kernel
jsgf855d93d2003-10-13 22:26:55 +000043 unmodified.
sewardjde4a1d02002-03-22 01:27:54 +000044
jsgf855d93d2003-10-13 22:26:55 +000045 A magical piece of assembly code, VG_(do_syscall)(), in vg_syscall.S
sewardjde4a1d02002-03-22 01:27:54 +000046 does the tricky bit of passing a syscall to the kernel, whilst
47 having the simulator retain control.
48*/
49
njn25e49d8e72002-09-23 09:36:25 +000050#define SYSCALL_TRACK(fn, args...) VG_TRACK(fn, Vg_CoreSysCall, ## args)
sewardjde4a1d02002-03-22 01:27:54 +000051
njn25e49d8e72002-09-23 09:36:25 +000052#define MAYBE_PRINTF(format, args...) \
53 if (VG_(clo_trace_syscalls)) \
54 VG_(printf)(format, ## args)
sewardjde4a1d02002-03-22 01:27:54 +000055
jsgf855d93d2003-10-13 22:26:55 +000056/* ---------------------------------------------------------------------
57 A simple atfork() facility for Valgrind's internal use
58 ------------------------------------------------------------------ */
59
60struct atfork {
61 vg_atfork_t pre;
62 vg_atfork_t parent;
63 vg_atfork_t child;
64};
65
66#define VG_MAX_ATFORK 10
67
68static struct atfork atforks[VG_MAX_ATFORK];
69static Int n_atfork;
70
71void VG_(atfork)(vg_atfork_t pre, vg_atfork_t parent, vg_atfork_t child)
72{
73 Int i;
74
75 for(i = 0; i < n_atfork; i++) {
76 if (atforks[i].pre == pre &&
77 atforks[i].parent == parent &&
78 atforks[i].child == child)
79 return;
80 }
81
82 if (n_atfork >= VG_MAX_ATFORK)
83 VG_(core_panic)("Too many VG_(atfork) handlers requested: raise VG_MAX_ATFORK");
84
85 atforks[n_atfork].pre = pre;
86 atforks[n_atfork].parent = parent;
87 atforks[n_atfork].child = child;
88
89 n_atfork++;
90}
91
92static void do_atfork_pre(ThreadId tid)
93{
94 Int i;
95
96 for(i = 0; i < n_atfork; i++)
97 if (atforks[i].pre != NULL)
98 (*atforks[i].pre)(tid);
99}
100
101static void do_atfork_parent(ThreadId tid)
102{
103 Int i;
104
105 for(i = 0; i < n_atfork; i++)
106 if (atforks[i].parent != NULL)
107 (*atforks[i].parent)(tid);
108}
109
110static void do_atfork_child(ThreadId tid)
111{
112 Int i;
113
114 for(i = 0; i < n_atfork; i++)
115 if (atforks[i].child != NULL)
116 (*atforks[i].child)(tid);
117}
118
fitzhardinge1a303042003-12-22 08:48:50 +0000119/* return true if address range entirely contained within client
120 address space */
nethercote1543adf2004-10-25 15:43:21 +0000121static Bool valid_client_addr(Addr start, UInt size, ThreadId tid, const Char *syscallname)
fitzhardinge1a303042003-12-22 08:48:50 +0000122{
123 Addr end = start+size;
124 Addr cl_base = VG_(client_base);
125 Bool ret;
126
127 if (size == 0)
128 return True;
129
130 if (cl_base < 0x10000)
131 cl_base = 0x10000;
132
133 ret =
134 (end >= start) &&
135 start >= cl_base && start < VG_(client_end) &&
136 (end <= VG_(client_end));
137
138 if (0)
139 VG_(printf)("%s: test=%p-%p client=%p-%p ret=%d\n",
nethercote1543adf2004-10-25 15:43:21 +0000140 syscallname, start, end, cl_base, VG_(client_end), ret);
fitzhardinge1a303042003-12-22 08:48:50 +0000141
nethercote1543adf2004-10-25 15:43:21 +0000142 if (!ret && syscallname != NULL) {
fitzhardinge1a303042003-12-22 08:48:50 +0000143 VG_(message)(Vg_UserMsg, "Warning: client syscall %s tried to modify addresses %p-%p",
nethercote1543adf2004-10-25 15:43:21 +0000144 syscallname, start, end);
fitzhardinge1a303042003-12-22 08:48:50 +0000145
146 if (VG_(clo_verbosity) > 1) {
147 ExeContext *ec = VG_(get_ExeContext)(tid);
148 VG_(pp_ExeContext)(ec);
149 }
150 }
151
152 return ret;
153}
154
njn25e49d8e72002-09-23 09:36:25 +0000155/* ---------------------------------------------------------------------
nethercote27ea8bc2004-07-10 17:21:14 +0000156 Doing mmap, mremap
njn25e49d8e72002-09-23 09:36:25 +0000157 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000158
njn25e49d8e72002-09-23 09:36:25 +0000159// Nb: this isn't done as precisely as possible, but it seems that programs
160// are usually sufficiently well-behaved that the more obscure corner cases
161// aren't important. Various comments in the few functions below give more
162// details... njn 2002-Sep-17
163
164/* AFAICT from kernel sources (mm/mprotect.c) and general experimentation,
165 munmap, mprotect (and mremap??) work at the page level. So addresses
166 and lengths must be adjusted for this. */
167
168/* Mash around start and length so that the area exactly covers
169 an integral number of pages. If we don't do that, memcheck's
170 idea of addressible memory diverges from that of the
171 kernel's, which causes the leak detector to crash. */
172static
173void mash_addr_and_len( Addr* a, UInt* len)
sewardjde4a1d02002-03-22 01:27:54 +0000174{
fitzhardinge98abfc72003-12-16 02:05:15 +0000175 Addr ra;
176
177 ra = PGROUNDDN(*a);
178 *len = PGROUNDUP(*a + *len) - ra;
179 *a = ra;
sewardjde4a1d02002-03-22 01:27:54 +0000180}
181
182static
fitzhardinge98abfc72003-12-16 02:05:15 +0000183void mmap_segment ( Addr a, UInt len, UInt prot, UInt mm_flags, Int fd, ULong offset )
sewardjde4a1d02002-03-22 01:27:54 +0000184{
sewardj40f8ebe2002-10-23 21:46:13 +0000185 Bool rr, ww, xx;
fitzhardinge98abfc72003-12-16 02:05:15 +0000186 UInt flags;
njn25e49d8e72002-09-23 09:36:25 +0000187
fitzhardinge98abfc72003-12-16 02:05:15 +0000188 flags = SF_MMAP;
189
190 if (mm_flags & VKI_MAP_FIXED)
191 flags |= SF_FIXED;
192 if (!(mm_flags & VKI_MAP_PRIVATE))
193 flags |= SF_SHARED;
194
195 if (fd != -1)
196 flags |= SF_FILE;
197
198 VG_(map_fd_segment)(a, len, prot, flags, fd, offset, NULL);
njn25e49d8e72002-09-23 09:36:25 +0000199
fitzhardinge1a303042003-12-22 08:48:50 +0000200 rr = prot & VKI_PROT_READ;
201 ww = prot & VKI_PROT_WRITE;
202 xx = prot & VKI_PROT_EXEC;
njn25e49d8e72002-09-23 09:36:25 +0000203
sewardj40f8ebe2002-10-23 21:46:13 +0000204 VG_TRACK( new_mem_mmap, a, len, rr, ww, xx );
sewardjde4a1d02002-03-22 01:27:54 +0000205}
206
njn25e49d8e72002-09-23 09:36:25 +0000207static
fitzhardinge1a303042003-12-22 08:48:50 +0000208Addr mremap_segment ( Addr old_addr, UInt old_size,
209 Addr new_addr, UInt new_size,
210 UInt flags, ThreadId tid)
njn25e49d8e72002-09-23 09:36:25 +0000211{
fitzhardinge1a303042003-12-22 08:48:50 +0000212 Addr ret;
213 Segment *seg, *next;
njn25e49d8e72002-09-23 09:36:25 +0000214
fitzhardinge1a303042003-12-22 08:48:50 +0000215 old_size = PGROUNDUP(old_size);
216 new_size = PGROUNDUP(new_size);
njn25e49d8e72002-09-23 09:36:25 +0000217
fitzhardinge1a303042003-12-22 08:48:50 +0000218 if (PGROUNDDN(old_addr) != old_addr)
219 return -VKI_EINVAL;
220
221 if (!valid_client_addr(old_addr, old_size, tid, "mremap(old_addr)"))
222 return -VKI_EFAULT;
223
224 /* fixed at the current address means we don't move it */
225 if ((flags & VKI_MREMAP_FIXED) && (old_addr == new_addr))
226 flags &= ~(VKI_MREMAP_FIXED|VKI_MREMAP_MAYMOVE);
227
228 if (flags & VKI_MREMAP_FIXED) {
229 if (PGROUNDDN(new_addr) != new_addr)
230 return -VKI_EINVAL;
231
232 if (!valid_client_addr(new_addr, new_size, tid, "mremap(new_addr)"))
233 return -VKI_ENOMEM;
234
235 /* check for overlaps */
236 if ((old_addr < (new_addr+new_size) &&
237 (old_addr+old_size) > new_addr) ||
238 (new_addr < (old_addr+new_size) &&
239 (new_addr+new_size) > old_addr))
240 return -VKI_EINVAL;
njn25e49d8e72002-09-23 09:36:25 +0000241 }
fitzhardinge1a303042003-12-22 08:48:50 +0000242
243 /* Do nothing */
244 if (!(flags & VKI_MREMAP_FIXED) && new_size == old_size)
245 return old_addr;
246
247 seg = VG_(find_segment)(old_addr);
248
249 /* range must be contained within segment */
250 if (seg == NULL || !VG_(seg_contains)(seg, old_addr, old_size))
251 return -VKI_EINVAL;
252
253 next = VG_(next_segment)(seg);
254
255 if (0)
256 VG_(printf)("mremap: old_addr+new_size=%p next->addr=%p flags=%d\n",
257 old_addr+new_size, next->addr, flags);
258
259 if ((flags & VKI_MREMAP_FIXED) ||
260 (next != NULL && (old_addr+new_size) > next->addr)) {
261 /* we're moving the block */
262 Addr a;
263
264 if ((flags & (VKI_MREMAP_FIXED|VKI_MREMAP_MAYMOVE)) == 0)
265 return -VKI_ENOMEM; /* not allowed to move */
266
267 if ((flags & VKI_MREMAP_FIXED) == 0)
268 new_addr = 0;
269
270 a = VG_(find_map_space)(new_addr, new_size, True);
271
272 if ((flags & VKI_MREMAP_FIXED) && a != new_addr)
273 return -VKI_ENOMEM; /* didn't find the place we wanted */
274
275 new_addr = a;
276 ret = a;
277
278 /* we've nailed down the location */
279 flags |= VKI_MREMAP_FIXED|VKI_MREMAP_MAYMOVE;
280
281 ret = VG_(do_syscall)(__NR_mremap, old_addr, old_size, new_size,
282 flags, new_addr);
283
284 if (ret != new_addr) {
285 vg_assert(VG_(is_kerror)(ret));
286 return ret;
287 }
288
289 VG_TRACK(copy_mem_remap, old_addr, new_addr,
290 (old_size < new_size) ? old_size : new_size);
291
292 if (new_size > old_size)
293 VG_TRACK(new_mem_mmap, new_addr+old_size, new_size-old_size,
294 seg->prot & VKI_PROT_READ,
295 seg->prot & VKI_PROT_WRITE,
296 seg->prot & VKI_PROT_EXEC);
297 VG_TRACK(die_mem_munmap, old_addr, old_size);
298
299 VG_(map_file_segment)(new_addr, new_size,
300 seg->prot,
301 seg->flags,
302 seg->dev, seg->ino,
303 seg->offset, seg->filename);
304
305 VG_(munmap)((void *)old_addr, old_size);
306 } else {
307 /* staying in place */
308 ret = old_addr;
309
310 if (new_size < old_size) {
311 VG_TRACK(die_mem_munmap, old_addr+new_size, old_size-new_size);
312 VG_(munmap)((void *)(old_addr+new_size), old_size-new_size);
313 } else {
314 /* we've nailed down the location */
315 flags &= ~VKI_MREMAP_MAYMOVE;
316
317 if (0)
318 VG_(printf)("mremap: old_addr=%p old_size=%d new_size=%d flags=%d\n",
319 old_addr, old_size, new_size, flags);
320
321 ret = VG_(do_syscall)(__NR_mremap, old_addr, old_size, new_size,
322 flags, 0);
323
324 if (ret != old_addr)
325 return ret;
326
327 VG_TRACK(new_mem_mmap, old_addr+old_size, new_size-old_size,
328 seg->prot & VKI_PROT_READ,
329 seg->prot & VKI_PROT_WRITE,
330 seg->prot & VKI_PROT_EXEC);
331
332 VG_(map_file_segment)(old_addr+old_size, new_size-old_size,
333 seg->prot,
334 seg->flags,
335 seg->dev, seg->ino,
336 seg->offset, seg->filename);
337 }
338 }
339
340 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000341}
342
343
344/* Is this a Linux kernel error return value? */
345/* From:
346 http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/sysdeps/unix/sysv/
347 linux/i386/sysdep.h?
348 rev=1.28&content-type=text/x-cvsweb-markup&cvsroot=glibc
349
njn25e49d8e72002-09-23 09:36:25 +0000350 \begin{quote}:
sewardjde4a1d02002-03-22 01:27:54 +0000351
352 Linux uses a negative return value to indicate syscall errors,
353 unlike most Unices, which use the condition codes' carry flag.
354
355 Since version 2.1 the return value of a system call might be
356 negative even if the call succeeded. E.g., the `lseek' system call
357 might return a large offset. Therefore we must not anymore test
358 for < 0, but test for a real error by making sure the value in %eax
359 is a real error number. Linus said he will make sure the no syscall
daywalker7e73e5f2003-07-04 16:18:15 +0000360 returns a value in -1 .. -4095 as a valid result so we can safely
sewardjde4a1d02002-03-22 01:27:54 +0000361 test with -4095.
362
363 END QUOTE
364*/
365Bool VG_(is_kerror) ( Int res )
366{
367 if (res >= -4095 && res <= -1)
368 return True;
369 else
370 return False;
371}
372
rjwalshf5f536f2003-11-17 17:45:00 +0000373/* One of these is allocated for each open file descriptor. */
374
375typedef struct OpenFd
376{
377 Int fd; /* The file descriptor */
378 Char *pathname; /* NULL if not a regular file or unknown */
379 ExeContext *where; /* NULL if inherited from parent */
380 struct OpenFd *next, *prev;
381} OpenFd;
382
383/* List of allocated file descriptors. */
384
385static OpenFd *allocated_fds;
386
387/* Count of open file descriptors. */
388
389static int fd_count = 0;
390
nethercoteccc9ecd2004-07-16 17:32:15 +0000391/* Given a file descriptor, attempt to deduce its filename. To do this,
rjwalshf5f536f2003-11-17 17:45:00 +0000392 we use /proc/self/fd/<FD>. If this doesn't point to a file, or if it
393 doesn't exist, we just return NULL. Otherwise, we return a pointer
394 to the file name, which the caller is responsible for freeing. */
395
fitzhardinge98abfc72003-12-16 02:05:15 +0000396Char *VG_(resolve_filename)(Int fd)
rjwalshf5f536f2003-11-17 17:45:00 +0000397{
398 char tmp[28], buf[PATH_MAX];
399
400 VG_(sprintf)(tmp, "/proc/self/fd/%d", fd);
401 VG_(memset)(buf, 0, PATH_MAX);
402
403 if(VG_(readlink)(tmp, buf, PATH_MAX) == -1)
404 return NULL;
405
fitzhardingea7728472003-12-16 01:48:38 +0000406 return ((buf[0] == '/') ? VG_(arena_strdup)(VG_AR_CORE, buf) : NULL);
rjwalshf5f536f2003-11-17 17:45:00 +0000407}
408
409
410/* Note the fact that a file descriptor was just closed. */
411
412static
413void record_fd_close(Int tid, Int fd)
414{
415 OpenFd *i = allocated_fds;
416
thughesad1c9562004-06-26 11:27:52 +0000417 if (fd >= VG_(fd_hard_limit))
rjwalsh02665ba2003-12-18 01:48:06 +0000418 return; /* Valgrind internal */
419
rjwalshf5f536f2003-11-17 17:45:00 +0000420 while(i) {
421 if(i->fd == fd) {
422 if(i->prev)
423 i->prev->next = i->next;
424 else
425 allocated_fds = i->next;
426 if(i->next)
427 i->next->prev = i->prev;
428 if(i->pathname)
fitzhardingea7728472003-12-16 01:48:38 +0000429 VG_(arena_free) (VG_AR_CORE, i->pathname);
430 VG_(arena_free) (VG_AR_CORE, i);
rjwalshf5f536f2003-11-17 17:45:00 +0000431 fd_count--;
432 break;
433 }
434 i = i->next;
435 }
436}
437
438/* Note the fact that a file descriptor was just opened. If the
439 tid is -1, this indicates an inherited fd. If the pathname is NULL,
440 this either indicates a non-standard file (i.e. a pipe or socket or
441 some such thing) or that we don't know the filename. If the fd is
442 already open, then we're probably doing a dup2() to an existing fd,
443 so just overwrite the existing one. */
444
445static
446void record_fd_open(Int tid, Int fd, char *pathname)
447{
448 OpenFd *i;
449
thughesad1c9562004-06-26 11:27:52 +0000450 if (fd >= VG_(fd_hard_limit))
fitzhardinge0e8bfcf2003-12-12 07:46:54 +0000451 return; /* Valgrind internal */
452
rjwalshf5f536f2003-11-17 17:45:00 +0000453 /* Check to see if this fd is already open. */
454 i = allocated_fds;
455 while (i) {
456 if (i->fd == fd) {
fitzhardingea7728472003-12-16 01:48:38 +0000457 if (i->pathname) VG_(arena_free)(VG_AR_CORE, i->pathname);
rjwalshf5f536f2003-11-17 17:45:00 +0000458 break;
459 }
460 i = i->next;
461 }
462
463 /* Not already one: allocate an OpenFd */
464 if (i == NULL) {
fitzhardingea7728472003-12-16 01:48:38 +0000465 i = VG_(arena_malloc)(VG_AR_CORE, sizeof(OpenFd));
rjwalshf5f536f2003-11-17 17:45:00 +0000466
467 i->prev = NULL;
468 i->next = allocated_fds;
469 if(allocated_fds) allocated_fds->prev = i;
470 allocated_fds = i;
471 fd_count++;
472 }
473
474 i->fd = fd;
475 i->pathname = pathname;
476 i->where = (tid == -1) ? NULL : VG_(get_ExeContext)(tid);
477}
478
479static
480Char *unix2name(struct sockaddr_un *sa, UInt len, Char *name)
481{
482 if(sa == NULL || len == 0 || sa->sun_path[0] == '\0') {
483 VG_(sprintf)(name, "<unknown>");
484 } else {
485 VG_(sprintf)(name, "%s", sa->sun_path);
486 }
487
488 return name;
489}
490
491static
492Char *inet2name(struct sockaddr_in *sa, UInt len, Char *name)
493{
494 if(sa == NULL || len == 0) {
495 VG_(sprintf)(name, "<unknown>");
496 } else {
497 UInt addr = sa->sin_addr.s_addr;
498
499 if (addr == 0) {
500 VG_(sprintf)(name, "<unbound>");
501 } else {
502 VG_(sprintf)(name, "%u.%u.%u.%u:%u",
503 addr & 0xFF, (addr>>8) & 0xFF,
504 (addr>>16) & 0xFF, (addr>>24) & 0xFF,
nethercote4ef5c392004-01-20 14:43:42 +0000505 ntohs(sa->sin_port));
rjwalshf5f536f2003-11-17 17:45:00 +0000506 }
507 }
508
509 return name;
510}
511
512
513/*
514 * Try get some details about a socket.
515 */
516
517static void
518getsockdetails(int fd)
519{
520 union u {
521 struct sockaddr a;
522 struct sockaddr_in in;
523 struct sockaddr_un un;
524 } laddr;
525 socklen_t llen;
526
527 llen = sizeof(laddr);
528 VG_(memset)(&laddr, 0, llen);
529
530 if(VG_(getsockname)(fd, (struct vki_sockaddr *)&(laddr.a), &llen) != -1) {
531 switch(laddr.a.sa_family) {
532 case AF_INET: {
533 static char lname[32];
534 static char pname[32];
535 struct sockaddr_in paddr;
536 socklen_t plen = sizeof(struct sockaddr_in);
537
538 if(VG_(getpeername)(fd, (struct vki_sockaddr *)&paddr, &plen) != -1) {
539 VG_(message)(Vg_UserMsg, "Open AF_INET socket %d: %s <-> %s", fd,
540 inet2name(&(laddr.in), llen, lname),
541 inet2name(&paddr, plen, pname));
542 } else {
543 VG_(message)(Vg_UserMsg, "Open AF_INET socket %d: %s <-> unbound",
544 fd, inet2name(&(laddr.in), llen, lname));
545 }
546 return;
547 }
548 case AF_UNIX: {
549 static char lname[256];
550 VG_(message)(Vg_UserMsg, "Open AF_UNIX socket %d: %s", fd,
551 unix2name(&(laddr.un), llen, lname));
552 return;
553 }
554 default:
555 VG_(message)(Vg_UserMsg, "Open pf-%d socket %d:",
556 laddr.a.sa_family, fd);
557 return;
558 }
559 }
560
561 VG_(message)(Vg_UserMsg, "Open socket %d:", fd);
562}
563
564
nethercote3a42fb82004-08-03 18:08:50 +0000565/* Dump out a summary, and a more detailed list, of open file descriptors. */
566void VG_(show_open_fds) ()
rjwalshf5f536f2003-11-17 17:45:00 +0000567{
568 OpenFd *i = allocated_fds;
569
nethercote3a42fb82004-08-03 18:08:50 +0000570 VG_(message)(Vg_UserMsg, "FILE DESCRIPTORS: %d open at exit.", fd_count);
rjwalshf5f536f2003-11-17 17:45:00 +0000571
572 while(i) {
573 if(i->pathname) {
574 VG_(message)(Vg_UserMsg, "Open file descriptor %d: %s", i->fd,
575 i->pathname);
576 } else {
577 int val;
578 socklen_t len = sizeof(val);
579
580 if(VG_(getsockopt)(i->fd, SOL_SOCKET, SO_TYPE, &val, &len) == -1) {
581 VG_(message)(Vg_UserMsg, "Open file descriptor %d:", i->fd);
582 } else {
583 getsockdetails(i->fd);
584 }
585 }
586
587 if(i->where) {
588 VG_(pp_ExeContext)(i->where);
589 VG_(message)(Vg_UserMsg, "");
590 } else {
591 VG_(message)(Vg_UserMsg, " <inherited from parent>");
592 VG_(message)(Vg_UserMsg, "");
593 }
594
595 i = i->next;
596 }
597
598 VG_(message)(Vg_UserMsg, "");
599}
600
601/* If /proc/self/fd doesn't exist for some weird reason (like you've
602 got a kernel that doesn't have /proc support compiled in), then we
603 need to find out what file descriptors we inherited from our parent
604 process the hard way - by checking each fd in turn. */
605
606static
607void do_hacky_preopened()
608{
609 struct vki_rlimit lim;
610 unsigned int count;
611 int i;
612
613 if(VG_(getrlimit) (VKI_RLIMIT_NOFILE, &lim) == -1) {
614 /* Hmm. getrlimit() failed. Now we're screwed, so just choose
615 an arbitrarily high number. 1024 happens to be the limit in
616 the 2.4 kernels. */
617 count = 1024;
618 } else {
619 count = lim.rlim_cur;
620 }
621
622 for (i = 0; i < count; i++)
623 if(VG_(fcntl)(i, VKI_F_GETFL, 0) != -1)
624 record_fd_open(-1, i, NULL);
625}
626
627/* Initialize the list of open file descriptors with the file descriptors
628 we inherited from out parent process. */
629
630void VG_(init_preopened_fds)()
631{
632 int f, ret;
633 struct vki_dirent d;
634
635 f = VG_(open)("/proc/self/fd", VKI_O_RDONLY, 0);
636 if(f == -1) {
637 do_hacky_preopened();
638 return;
639 }
640
641 while((ret = VG_(getdents)(f, &d, sizeof(d))) != 0) {
642 if(ret == -1)
643 goto out;
644
645 if(VG_(strcmp)(d.d_name, ".") && VG_(strcmp)(d.d_name, "..")) {
646 int fno = VG_(atoll)(d.d_name);
647
648 if(fno != f)
649 if(VG_(clo_track_fds))
fitzhardinge98abfc72003-12-16 02:05:15 +0000650 record_fd_open(-1, fno, VG_(resolve_filename)(fno));
rjwalshf5f536f2003-11-17 17:45:00 +0000651 }
652
653 VG_(lseek)(f, d.d_off, VKI_SEEK_SET);
654 }
655
656out:
657 VG_(close)(f);
658}
659
sewardjde4a1d02002-03-22 01:27:54 +0000660static
661UInt get_shm_size ( Int shmid )
662{
663 struct shmid_ds buf;
jsgf855d93d2003-10-13 22:26:55 +0000664 long __res = VG_(do_syscall)(__NR_ipc, 24 /* IPCOP_shmctl */, shmid, IPC_STAT, 0, &buf);
sewardjde4a1d02002-03-22 01:27:54 +0000665 if ( VG_(is_kerror) ( __res ) )
666 return 0;
667
668 return buf.shm_segsz;
669}
thughes60797102004-08-13 22:21:51 +0000670
671static
672UInt get_sem_count( Int semid )
673{
674 struct semid_ds buf;
675 union semun arg;
676 long res;
677
678 arg.buf = &buf;
679
680 res = VG_(do_syscall)(__NR_ipc, 3 /* IPCOP_semctl */, semid, 0, IPC_STAT, &arg);
681 if ( VG_(is_kerror)(res) )
682 return 0;
683
684 return buf.sem_nsems;
685}
sewardjde4a1d02002-03-22 01:27:54 +0000686
687static
sewardj8c824512002-04-14 04:16:48 +0000688Char *strdupcat ( const Char *s1, const Char *s2, ArenaId aid )
sewardjde4a1d02002-03-22 01:27:54 +0000689{
690 UInt len = VG_(strlen) ( s1 ) + VG_(strlen) ( s2 ) + 1;
njn25e49d8e72002-09-23 09:36:25 +0000691 Char *result = VG_(arena_malloc) ( aid, len );
sewardjde4a1d02002-03-22 01:27:54 +0000692 VG_(strcpy) ( result, s1 );
693 VG_(strcat) ( result, s2 );
694 return result;
695}
696
697static
jsgf855d93d2003-10-13 22:26:55 +0000698void pre_mem_read_sendmsg ( ThreadId tid,
699 Char *msg, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +0000700{
701 Char *outmsg = strdupcat ( "socketcall.sendmsg", msg, VG_AR_TRANSIENT );
njn72718642003-07-24 08:45:32 +0000702 SYSCALL_TRACK( pre_mem_read, tid, outmsg, base, size );
njn25e49d8e72002-09-23 09:36:25 +0000703
704 VG_(arena_free) ( VG_AR_TRANSIENT, outmsg );
sewardjde4a1d02002-03-22 01:27:54 +0000705}
706
707static
jsgf855d93d2003-10-13 22:26:55 +0000708void pre_mem_write_recvmsg ( ThreadId tid,
709 Char *msg, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +0000710{
711 Char *outmsg = strdupcat ( "socketcall.recvmsg", msg, VG_AR_TRANSIENT );
njn72718642003-07-24 08:45:32 +0000712 SYSCALL_TRACK( pre_mem_write, tid, outmsg, base, size );
njn25e49d8e72002-09-23 09:36:25 +0000713 VG_(arena_free) ( VG_AR_TRANSIENT, outmsg );
sewardjde4a1d02002-03-22 01:27:54 +0000714}
715
716static
njn72718642003-07-24 08:45:32 +0000717void post_mem_write_recvmsg ( ThreadId tid,
njn25e49d8e72002-09-23 09:36:25 +0000718 Char *fieldName, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +0000719{
njn25e49d8e72002-09-23 09:36:25 +0000720 VG_TRACK( post_mem_write, base, size );
sewardjde4a1d02002-03-22 01:27:54 +0000721}
722
723static
sewardj8c824512002-04-14 04:16:48 +0000724void msghdr_foreachfield (
njn72718642003-07-24 08:45:32 +0000725 ThreadId tid,
sewardj8c824512002-04-14 04:16:48 +0000726 struct msghdr *msg,
njn72718642003-07-24 08:45:32 +0000727 void (*foreach_func)( ThreadId, Char *, UInt, UInt )
sewardj8c824512002-04-14 04:16:48 +0000728 )
sewardjde4a1d02002-03-22 01:27:54 +0000729{
730 if ( !msg )
731 return;
732
njn72718642003-07-24 08:45:32 +0000733 foreach_func ( tid, "(msg)", (Addr)msg, sizeof( struct msghdr ) );
sewardjde4a1d02002-03-22 01:27:54 +0000734
735 if ( msg->msg_name )
njn72718642003-07-24 08:45:32 +0000736 foreach_func ( tid,
sewardj8c824512002-04-14 04:16:48 +0000737 "(msg.msg_name)",
sewardjde4a1d02002-03-22 01:27:54 +0000738 (Addr)msg->msg_name, msg->msg_namelen );
739
740 if ( msg->msg_iov ) {
741 struct iovec *iov = msg->msg_iov;
742 UInt i;
743
njn72718642003-07-24 08:45:32 +0000744 foreach_func ( tid,
sewardj8c824512002-04-14 04:16:48 +0000745 "(msg.msg_iov)",
sewardjde4a1d02002-03-22 01:27:54 +0000746 (Addr)iov, msg->msg_iovlen * sizeof( struct iovec ) );
747
748 for ( i = 0; i < msg->msg_iovlen; ++i, ++iov )
njn72718642003-07-24 08:45:32 +0000749 foreach_func ( tid,
sewardj8c824512002-04-14 04:16:48 +0000750 "(msg.msg_iov[i]",
sewardjde4a1d02002-03-22 01:27:54 +0000751 (Addr)iov->iov_base, iov->iov_len );
752 }
753
754 if ( msg->msg_control )
njn72718642003-07-24 08:45:32 +0000755 foreach_func ( tid,
sewardj8c824512002-04-14 04:16:48 +0000756 "(msg.msg_control)",
sewardjde4a1d02002-03-22 01:27:54 +0000757 (Addr)msg->msg_control, msg->msg_controllen );
758}
759
rjwalshf5f536f2003-11-17 17:45:00 +0000760void check_cmsg_for_fds(Int tid, struct msghdr *msg)
761{
762 struct cmsghdr *cm = CMSG_FIRSTHDR(msg);
763
764 while (cm) {
765 if (cm->cmsg_level == SOL_SOCKET &&
766 cm->cmsg_type == SCM_RIGHTS ) {
767 int *fds = (int *) CMSG_DATA(cm);
768 int fdc = (cm->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)))
769 / sizeof(int);
770 int i;
771
772 for (i = 0; i < fdc; i++)
773 if(VG_(clo_track_fds))
nethercote493dd182004-02-24 23:57:47 +0000774 // XXX: must we check the range on these fds with
775 // fd_allowed()?
fitzhardinge98abfc72003-12-16 02:05:15 +0000776 record_fd_open (tid, fds[i], VG_(resolve_filename)(fds[i]));
rjwalshf5f536f2003-11-17 17:45:00 +0000777 }
778
779 cm = CMSG_NXTHDR(msg, cm);
780 }
781}
782
sewardjc483e8f2002-05-03 21:01:35 +0000783static
jsgf855d93d2003-10-13 22:26:55 +0000784void pre_mem_read_sockaddr ( ThreadId tid,
785 Char *description,
786 struct sockaddr *sa, UInt salen )
sewardjc483e8f2002-05-03 21:01:35 +0000787{
sewardjff7c1ab2003-02-24 21:55:34 +0000788 Char *outmsg;
789
790 /* NULL/zero-length sockaddrs are legal */
791 if ( sa == NULL || salen == 0 ) return;
792
793 outmsg = VG_(arena_malloc) ( VG_AR_TRANSIENT,
794 strlen( description ) + 30 );
sewardjc483e8f2002-05-03 21:01:35 +0000795
796 VG_(sprintf) ( outmsg, description, ".sa_family" );
njn72718642003-07-24 08:45:32 +0000797 SYSCALL_TRACK( pre_mem_read, tid, outmsg,
nethercotea8c1e922004-10-26 10:57:24 +0000798 (Addr) &sa->sa_family, sizeof (sa_family_t));
jsgf855d93d2003-10-13 22:26:55 +0000799
sewardjc483e8f2002-05-03 21:01:35 +0000800 switch (sa->sa_family) {
801
802 case AF_UNIX:
803 VG_(sprintf) ( outmsg, description, ".sun_path" );
njn72718642003-07-24 08:45:32 +0000804 SYSCALL_TRACK( pre_mem_read_asciiz, tid, outmsg,
nethercotea8c1e922004-10-26 10:57:24 +0000805 (Addr) ((struct sockaddr_un *) sa)->sun_path);
sewardjc483e8f2002-05-03 21:01:35 +0000806 break;
807
808 case AF_INET:
809 VG_(sprintf) ( outmsg, description, ".sin_port" );
njn72718642003-07-24 08:45:32 +0000810 SYSCALL_TRACK( pre_mem_read, tid, outmsg,
nethercotea8c1e922004-10-26 10:57:24 +0000811 (Addr) &((struct sockaddr_in *) sa)->sin_port,
sewardj32102152002-05-04 10:28:17 +0000812 sizeof (((struct sockaddr_in *) sa)->sin_port));
sewardjc483e8f2002-05-03 21:01:35 +0000813 VG_(sprintf) ( outmsg, description, ".sin_addr" );
njn72718642003-07-24 08:45:32 +0000814 SYSCALL_TRACK( pre_mem_read, tid, outmsg,
nethercotea8c1e922004-10-26 10:57:24 +0000815 (Addr) &((struct sockaddr_in *) sa)->sin_addr,
sewardjc483e8f2002-05-03 21:01:35 +0000816 sizeof (struct in_addr));
817 break;
818
819 case AF_INET6:
820 VG_(sprintf) ( outmsg, description, ".sin6_port" );
njn72718642003-07-24 08:45:32 +0000821 SYSCALL_TRACK( pre_mem_read, tid, outmsg,
nethercotea8c1e922004-10-26 10:57:24 +0000822 (Addr) &((struct sockaddr_in6 *) sa)->sin6_port,
sewardj32102152002-05-04 10:28:17 +0000823 sizeof (((struct sockaddr_in6 *) sa)->sin6_port));
sewardjc483e8f2002-05-03 21:01:35 +0000824 VG_(sprintf) ( outmsg, description, ".sin6_flowinfo" );
njn72718642003-07-24 08:45:32 +0000825 SYSCALL_TRACK( pre_mem_read, tid, outmsg,
nethercotea8c1e922004-10-26 10:57:24 +0000826 (Addr) &((struct sockaddr_in6 *) sa)->sin6_flowinfo,
sewardjc483e8f2002-05-03 21:01:35 +0000827 sizeof (uint32_t));
828 VG_(sprintf) ( outmsg, description, ".sin6_addr" );
njn72718642003-07-24 08:45:32 +0000829 SYSCALL_TRACK( pre_mem_read, tid, outmsg,
nethercotea8c1e922004-10-26 10:57:24 +0000830 (Addr) &((struct sockaddr_in6 *) sa)->sin6_addr,
sewardjc483e8f2002-05-03 21:01:35 +0000831 sizeof (struct in6_addr));
sewardj32102152002-05-04 10:28:17 +0000832# ifndef GLIBC_2_1
sewardjc483e8f2002-05-03 21:01:35 +0000833 VG_(sprintf) ( outmsg, description, ".sin6_scope_id" );
njn72718642003-07-24 08:45:32 +0000834 SYSCALL_TRACK( pre_mem_read, tid, outmsg,
nethercotea8c1e922004-10-26 10:57:24 +0000835 (Addr) &((struct sockaddr_in6 *) sa)->sin6_scope_id,
jsgf855d93d2003-10-13 22:26:55 +0000836 sizeof (uint32_t));
sewardj32102152002-05-04 10:28:17 +0000837# endif
sewardjc483e8f2002-05-03 21:01:35 +0000838 break;
839
840 default:
841 VG_(sprintf) ( outmsg, description, "" );
nethercotea8c1e922004-10-26 10:57:24 +0000842 SYSCALL_TRACK( pre_mem_read, tid, outmsg, (Addr) sa, salen );
sewardjc483e8f2002-05-03 21:01:35 +0000843 break;
844 }
845
njn25e49d8e72002-09-23 09:36:25 +0000846 VG_(arena_free) ( VG_AR_TRANSIENT, outmsg );
sewardjc483e8f2002-05-03 21:01:35 +0000847}
848
njn25e49d8e72002-09-23 09:36:25 +0000849/* Dereference a pointer to a UInt. */
njn72718642003-07-24 08:45:32 +0000850static UInt deref_UInt ( ThreadId tid, Addr a, Char* s )
njn25e49d8e72002-09-23 09:36:25 +0000851{
852 UInt* a_p = (UInt*)a;
njn72718642003-07-24 08:45:32 +0000853 SYSCALL_TRACK( pre_mem_read, tid, s, (Addr)a_p, sizeof(UInt) );
njn25e49d8e72002-09-23 09:36:25 +0000854 if (a_p == NULL)
855 return 0;
856 else
857 return *a_p;
858}
859
860/* Dereference a pointer to a pointer. */
njn72718642003-07-24 08:45:32 +0000861static Addr deref_Addr ( ThreadId tid, Addr a, Char* s )
njn25e49d8e72002-09-23 09:36:25 +0000862{
863 Addr* a_p = (Addr*)a;
njn72718642003-07-24 08:45:32 +0000864 SYSCALL_TRACK( pre_mem_read, tid, s, (Addr)a_p, sizeof(Addr) );
njn25e49d8e72002-09-23 09:36:25 +0000865 return *a_p;
866}
867
868static
njn72718642003-07-24 08:45:32 +0000869void buf_and_len_pre_check( ThreadId tid, Addr buf_p, Addr buflen_p,
njn25e49d8e72002-09-23 09:36:25 +0000870 Char* buf_s, Char* buflen_s )
871{
fitzhardinge98abfc72003-12-16 02:05:15 +0000872 if (VG_(defined_pre_mem_write)()) {
njn72718642003-07-24 08:45:32 +0000873 UInt buflen_in = deref_UInt( tid, buflen_p, buflen_s);
njn25e49d8e72002-09-23 09:36:25 +0000874 if (buflen_in > 0) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000875 SK_(pre_mem_write) ( Vg_CoreSysCall,
876 tid, buf_s, buf_p, buflen_in );
njn25e49d8e72002-09-23 09:36:25 +0000877 }
878 }
879}
880
881static
njn72718642003-07-24 08:45:32 +0000882void buf_and_len_post_check( ThreadId tid, Int res,
njn25e49d8e72002-09-23 09:36:25 +0000883 Addr buf_p, Addr buflen_p, Char* s )
884{
fitzhardinge98abfc72003-12-16 02:05:15 +0000885 if (!VG_(is_kerror)(res) && VG_(defined_post_mem_write)()) {
njn72718642003-07-24 08:45:32 +0000886 UInt buflen_out = deref_UInt( tid, buflen_p, s);
njn25e49d8e72002-09-23 09:36:25 +0000887 if (buflen_out > 0 && buf_p != (Addr)NULL) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000888 SK_(post_mem_write) ( buf_p, buflen_out );
njn25e49d8e72002-09-23 09:36:25 +0000889 }
890 }
891}
892
893/* ---------------------------------------------------------------------
894 Data seg end, for brk()
895 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000896
fitzhardinge98abfc72003-12-16 02:05:15 +0000897static Addr do_brk(Addr newbrk)
njn25e49d8e72002-09-23 09:36:25 +0000898{
fitzhardinge98abfc72003-12-16 02:05:15 +0000899 Addr ret = VG_(brk_limit);
900 static const Bool debug = False;
901 Segment *seg;
nethercotece471262004-08-25 13:43:44 +0000902 Addr current, newaddr;
903
fitzhardinge98abfc72003-12-16 02:05:15 +0000904
905 if (debug)
906 VG_(printf)("do_brk: brk_base=%p brk_limit=%p newbrk=%p\n",
907 VG_(brk_base), VG_(brk_limit), newbrk);
908
909 if (newbrk < VG_(brk_base) || newbrk >= VG_(client_end))
910 return VG_(brk_limit);
911
912 /* brk isn't allowed to grow over anything else */
913 seg = VG_(find_segment)(VG_(brk_limit));
914
915 vg_assert(seg != NULL);
916
njn25e49d8e72002-09-23 09:36:25 +0000917 if (0)
fitzhardinge98abfc72003-12-16 02:05:15 +0000918 VG_(printf)("brk_limit=%p seg->addr=%p seg->end=%p\n",
919 VG_(brk_limit), seg->addr, seg->addr+seg->len);
920 vg_assert(VG_(brk_limit) >= seg->addr && VG_(brk_limit) <= (seg->addr + seg->len));
921
922 seg = VG_(next_segment)(seg);
923 if (seg != NULL && newbrk > seg->addr)
924 return VG_(brk_limit);
925
nethercotece471262004-08-25 13:43:44 +0000926 current = PGROUNDUP(VG_(brk_limit));
927 newaddr = PGROUNDUP(newbrk);
928 if (newaddr != current) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000929
930 /* new brk in a new page - fix the mappings */
931 if (newbrk > VG_(brk_limit)) {
932
933 if (debug)
934 VG_(printf)(" extending brk: current=%p newaddr=%p delta=%d\n",
935 current, newaddr, newaddr-current);
936
937 if (newaddr == current) {
938 ret = newbrk;
nethercoteb4250ae2004-07-10 16:50:09 +0000939 } else if ((void*)-1 != VG_(mmap)((void*)current, newaddr-current,
940 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC,
941 VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS|VKI_MAP_FIXED|VKI_MAP_CLIENT,
942 SF_FIXED|SF_BRK, -1, 0))
943 {
fitzhardinge98abfc72003-12-16 02:05:15 +0000944 ret = newbrk;
945 }
946 } else {
947 vg_assert(newbrk < VG_(brk_limit));
948
949 if (debug)
950 VG_(printf)(" shrinking brk: current=%p newaddr=%p delta=%d\n",
951 current, newaddr, current-newaddr);
952
953 if (newaddr != current) {
nethercotee567e702004-07-10 17:49:17 +0000954 int res = VG_(munmap)((void *)newaddr, current - newaddr);
955 vg_assert(0 == res);
fitzhardinge98abfc72003-12-16 02:05:15 +0000956 }
957 ret = newbrk;
958 }
959 } else
960 ret = newbrk;
961
962 VG_(brk_limit) = ret;
963
964 return ret;
965}
966
967
njn25e49d8e72002-09-23 09:36:25 +0000968/* ---------------------------------------------------------------------
jsgf855d93d2003-10-13 22:26:55 +0000969 Vet file descriptors for sanity
970 ------------------------------------------------------------------ */
971
972/* Return true if we're allowed to use or create this fd */
nethercote1543adf2004-10-25 15:43:21 +0000973static Bool fd_allowed(Int fd, const Char *syscallname, ThreadId tid, Bool soft)
jsgf855d93d2003-10-13 22:26:55 +0000974{
thughesad1c9562004-06-26 11:27:52 +0000975 if (fd < 0 || fd >= VG_(fd_hard_limit) || fd == VG_(clo_log_fd)) {
jsewardd9320a42003-12-12 06:40:05 +0000976 VG_(message)(Vg_UserMsg,
977 "Warning: invalid file descriptor %d in syscall %s()",
nethercote1543adf2004-10-25 15:43:21 +0000978 fd, syscallname);
nethercotef8548672004-06-21 12:42:35 +0000979 if (fd == VG_(clo_log_fd))
jsewardd9320a42003-12-12 06:40:05 +0000980 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +0000981 " Use --log-fd=<number> to select an alternative log fd.");
jsgf855d93d2003-10-13 22:26:55 +0000982 if (VG_(clo_verbosity) > 1) {
983 ExeContext *ec = VG_(get_ExeContext)(tid);
984 VG_(pp_ExeContext)(ec);
985 }
986 return False;
987 }
thughesad1c9562004-06-26 11:27:52 +0000988 else if (soft && fd >= VG_(fd_soft_limit)) {
989 return False;
990 }
jsgf855d93d2003-10-13 22:26:55 +0000991 return True;
992}
993
994
995/* ---------------------------------------------------------------------
njn25e49d8e72002-09-23 09:36:25 +0000996 The Main Entertainment ...
997 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000998
thughesbaa46e52004-07-29 17:44:23 +0000999#define MayBlock (1 << 0)
1000#define PostOnFail (1 << 1)
jsgf855d93d2003-10-13 22:26:55 +00001001
1002#define PRE(x) \
1003 static void before_##x(ThreadId tid, ThreadState *tst)
1004#define POST(x) \
1005 static void after_##x(ThreadId tid, ThreadState *tst)
1006
jsgf855d93d2003-10-13 22:26:55 +00001007#define PREALIAS(new, old) \
1008 PRE(new) __attribute__((alias(STR(before_##old))))
1009#define POSTALIAS(new, old) \
1010 POST(new) __attribute__((alias(STR(after_##old))))
1011
nethercotebb4222b2004-09-10 17:42:11 +00001012#define SYSNO PLATFORM_SYSCALL_NUM(tst->arch) // in PRE(x)
1013#define res PLATFORM_SYSCALL_RET(tst->arch) // in POST(x)
1014#define arg1 PLATFORM_SYSCALL_ARG1(tst->arch)
1015#define arg2 PLATFORM_SYSCALL_ARG2(tst->arch)
1016#define arg3 PLATFORM_SYSCALL_ARG3(tst->arch)
1017#define arg4 PLATFORM_SYSCALL_ARG4(tst->arch)
1018#define arg5 PLATFORM_SYSCALL_ARG5(tst->arch)
1019#define arg6 PLATFORM_SYSCALL_ARG6(tst->arch)
jsgf855d93d2003-10-13 22:26:55 +00001020
nethercote35122912004-10-18 17:00:30 +00001021#define set_result(val) PLATFORM_SET_SYSCALL_RESULT(tst->arch, (val))
1022
jsgf855d93d2003-10-13 22:26:55 +00001023PRE(exit_group)
1024{
1025 VG_(core_panic)("syscall exit_group() not caught by the scheduler?!");
1026}
1027
1028PRE(exit)
1029{
1030 VG_(core_panic)("syscall exit() not caught by the scheduler?!");
1031}
1032
jsgf855d93d2003-10-13 22:26:55 +00001033PRE(ptrace)
1034{
1035 /* long ptrace (enum __ptrace_request request, pid_t pid,
nethercotee70bd7d2004-08-18 14:37:17 +00001036 void *addr, void *data); */
jsgf855d93d2003-10-13 22:26:55 +00001037 MAYBE_PRINTF("ptrace ( %d, %d, %p, %p )\n", arg1,arg2,arg3,arg4);
1038 switch (arg1) {
1039 case 12: /* PTRACE_GETREGS */
1040 SYSCALL_TRACK( pre_mem_write, tid, "ptrace(getregs)", arg4,
1041 sizeof (struct user_regs_struct));
1042 break;
1043 case 14: /* PTRACE_GETFPREGS */
1044 SYSCALL_TRACK( pre_mem_write, tid, "ptrace(getfpregs)", arg4,
fitzhardinged65dcad2004-03-13 02:06:58 +00001045 sizeof (struct user_i387_struct));
jsgf855d93d2003-10-13 22:26:55 +00001046 break;
1047 case 18: /* PTRACE_GETFPXREGS */
1048 SYSCALL_TRACK( pre_mem_write, tid, "ptrace(getfpxregs)", arg4,
nethercotee70bd7d2004-08-18 14:37:17 +00001049 sizeof(struct user_fxsr_struct) );
jsgf855d93d2003-10-13 22:26:55 +00001050 break;
1051 case 1: case 2: case 3: /* PTRACE_PEEK{TEXT,DATA,USER} */
1052 SYSCALL_TRACK( pre_mem_write, tid, "ptrace(peek)", arg4,
1053 sizeof (long));
1054 break;
1055 case 13: /* PTRACE_SETREGS */
1056 SYSCALL_TRACK( pre_mem_read, tid, "ptrace(setregs)", arg4,
1057 sizeof (struct user_regs_struct));
1058 break;
1059 case 15: /* PTRACE_SETFPREGS */
1060 SYSCALL_TRACK( pre_mem_read, tid, "ptrace(setfpregs)", arg4,
fitzhardinged65dcad2004-03-13 02:06:58 +00001061 sizeof (struct user_i387_struct));
jsgf855d93d2003-10-13 22:26:55 +00001062 break;
1063 case 19: /* PTRACE_SETFPXREGS */
1064 SYSCALL_TRACK( pre_mem_read, tid, "ptrace(setfpxregs)", arg4,
nethercotee70bd7d2004-08-18 14:37:17 +00001065 sizeof(struct user_fxsr_struct) );
jsgf855d93d2003-10-13 22:26:55 +00001066 break;
1067 default:
1068 break;
1069 }
1070}
1071
1072POST(ptrace)
1073{
jsgf855d93d2003-10-13 22:26:55 +00001074 switch (arg1) {
1075 case 12: /* PTRACE_GETREGS */
1076 VG_TRACK( post_mem_write, arg4,
1077 sizeof (struct user_regs_struct));
1078 break;
1079 case 14: /* PTRACE_GETFPREGS */
1080 VG_TRACK( post_mem_write, arg4,
fitzhardinged65dcad2004-03-13 02:06:58 +00001081 sizeof (struct user_i387_struct));
jsgf855d93d2003-10-13 22:26:55 +00001082 break;
1083 case 18: /* PTRACE_GETFPXREGS */
1084 VG_TRACK( post_mem_write, arg4,
nethercotee70bd7d2004-08-18 14:37:17 +00001085 sizeof(struct user_fxsr_struct) );
jsgf855d93d2003-10-13 22:26:55 +00001086 break;
1087 case 1: case 2: case 3: /* PTRACE_PEEK{TEXT,DATA,USER} */
1088 VG_TRACK( post_mem_write, arg4, sizeof (long));
1089 break;
1090 default:
1091 break;
1092 }
1093}
1094
1095PRE(mount)
1096{
nethercotee70bd7d2004-08-18 14:37:17 +00001097 // int mount(const char *source, const char *target,
1098 // const char *filesystemtype, unsigned long mountflags,
1099 // const void *data);
1100 MAYBE_PRINTF( "mount( %p, %p, %p, %p, %p )\n" ,arg1,arg2,arg3);
jsgf855d93d2003-10-13 22:26:55 +00001101 SYSCALL_TRACK( pre_mem_read_asciiz, tid,"mount(specialfile)",arg1);
1102 SYSCALL_TRACK( pre_mem_read_asciiz, tid,"mount(dir)",arg2);
1103 SYSCALL_TRACK( pre_mem_read_asciiz, tid,"mount(filesystemtype)",arg3);
1104}
1105
1106PRE(umount)
1107{
1108 /* int umount(const char *path) */
1109 MAYBE_PRINTF("umount( %p )\n", arg1);
1110 SYSCALL_TRACK( pre_mem_read_asciiz, tid,"umount(path)",arg1);
1111}
1112
1113PRE(modify_ldt)
1114{
1115 MAYBE_PRINTF("modify_ldt ( %d, %p, %d )\n", arg1,arg2,arg3);
1116 if (arg1 == 0) {
1117 /* read the LDT into ptr */
1118 SYSCALL_TRACK( pre_mem_write, tid,
1119 "modify_ldt(ptr)(func=0)", arg2, arg3 );
1120 }
1121 if (arg1 == 1 || arg1 == 0x11) {
1122 /* write the LDT with the entry pointed at by ptr */
1123 SYSCALL_TRACK( pre_mem_read, tid,
1124 "modify_ldt(ptr)(func=1 or 0x11)", arg2,
1125 sizeof(struct vki_modify_ldt_ldt_s) );
1126 }
1127 /* "do" the syscall ourselves; the kernel never sees it */
1128 res = VG_(sys_modify_ldt)( tid, arg1, (void*)arg2, arg3 );
1129
1130 if (arg1 == 0 && !VG_(is_kerror)(res) && res > 0) {
1131 VG_TRACK( post_mem_write, arg2, res );
1132 }
1133}
1134
fitzhardinge47735af2004-01-21 01:27:27 +00001135PRE(set_thread_area)
1136{
1137 MAYBE_PRINTF("set_thread_area ( %p )\n", arg1);
1138
1139 SYSCALL_TRACK( pre_mem_read, tid,
1140 "set_thread_area(ptr)", arg1,
1141 sizeof(struct vki_modify_ldt_ldt_s) );
1142
1143 /* "do" the syscall ourselves; the kernel never sees it */
nethercote35122912004-10-18 17:00:30 +00001144 set_result( VG_(sys_set_thread_area)( tid, (void *)arg1 ) );
fitzhardinge47735af2004-01-21 01:27:27 +00001145}
1146
1147PRE(get_thread_area)
1148{
1149 MAYBE_PRINTF("get_thread_area ( %p )\n", arg1);
1150 SYSCALL_TRACK( pre_mem_write, tid,
1151 "get_thread_area(ptr)", arg1,
1152 sizeof(struct vki_modify_ldt_ldt_s) );
1153
1154 /* "do" the syscall ourselves; the kernel never sees it */
nethercote35122912004-10-18 17:00:30 +00001155 set_result( VG_(sys_get_thread_area)( tid, (void *)arg1 ) );
fitzhardinge47735af2004-01-21 01:27:27 +00001156
1157 if (!VG_(is_kerror)(res)) {
1158 VG_TRACK( post_mem_write, arg1, sizeof(struct vki_modify_ldt_ldt_s) );
1159 }
1160}
1161
rjwalshcdf1cb52004-04-29 08:40:50 +00001162PRE(set_tid_address)
1163{
1164 MAYBE_PRINTF("set_tid_address ( %p )\n", arg1);
1165}
1166
jsgf855d93d2003-10-13 22:26:55 +00001167PRE(setresgid)
1168{
1169 /* int setresgid(gid_t rgid, gid_t egid, gid_t sgid); */
1170 MAYBE_PRINTF("setresgid ( %d, %d, %d )\n", arg1, arg2, arg3);
1171}
1172
1173PRE(vhangup)
1174{
1175 MAYBE_PRINTF("vhangup()\n");
1176}
1177
1178PRE(iopl)
1179{
1180 MAYBE_PRINTF("iopl ( %d )\n", arg1);
1181}
1182
1183PRE(setxattr)
1184{
1185 MAYBE_PRINTF("setxattr ( %p, %p, %p, %d, %d )\n",
1186 arg1, arg2, arg3, arg4, arg5);
1187 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "setxattr(path)", arg1 );
1188 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "setxattr(name)", arg2 );
1189 SYSCALL_TRACK( pre_mem_read, tid, "setxattr(value)", arg3, arg4 );
1190}
1191
1192PREALIAS(lsetxattr, setxattr);
1193
1194PRE(fsetxattr)
1195{
1196 /* int fsetxattr (int filedes, const char *name,
1197 const void *value, size_t size, int flags); */
1198 MAYBE_PRINTF("fsetxattr ( %d, %p, %p, %d, %d )\n",
1199 arg1, arg2, arg3, arg4, arg5);
1200 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "fsetxattr(name)", arg2 );
1201 SYSCALL_TRACK( pre_mem_read, tid, "fsetxattr(value)", arg3, arg4 );
1202}
1203
1204PRE(getxattr)
1205{
1206 MAYBE_PRINTF("getxattr ( %p, %p, %p, %d )\n",
1207 arg1,arg2,arg3, arg4);
1208 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "getxattr(path)", arg1 );
1209 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "getxattr(name)", arg2 );
1210 SYSCALL_TRACK( pre_mem_write, tid, "getxattr(value)", arg3, arg4 );
1211}
1212
1213POST(getxattr)
1214{
1215 if (res > 0 && arg3 != (Addr)NULL) {
1216 VG_TRACK( post_mem_write, arg3, res );
1217 }
1218}
1219
1220PREALIAS(lgetxattr, getxattr);
1221POSTALIAS(lgetxattr, getxattr);
1222
1223PRE(fgetxattr)
1224{
1225 MAYBE_PRINTF("fgetxattr ( %d, %p, %p, %d )\n",
1226 arg1, arg2, arg3, arg4);
1227 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "fgetxattr(name)", arg2 );
1228 SYSCALL_TRACK( pre_mem_write, tid, "fgetxattr(value)", arg3, arg4 );
1229}
1230
1231POST(fgetxattr)
1232{
1233 if (res > 0 && arg3 != (Addr)NULL)
1234 VG_TRACK( post_mem_write, arg3, res );
1235}
1236
1237PRE(listxattr)
1238{
1239 MAYBE_PRINTF("listxattr ( %p, %p, %d )\n", arg1, arg2, arg3);
1240 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "listxattr(path)", arg1 );
1241 SYSCALL_TRACK( pre_mem_write, tid, "listxattr(list)", arg2, arg3 );
1242}
1243
1244POST(listxattr)
1245{
1246 if (res > 0 && arg2 != (Addr)NULL)
1247 VG_TRACK( post_mem_write, arg2, res );
1248}
1249
1250PREALIAS(llistxattr, listxattr);
1251POSTALIAS(llistxattr, listxattr);
1252
1253PRE(flistxattr)
1254{
1255 /* ssize_t flistxattr (int filedes, char *list, size_t size); */
1256 MAYBE_PRINTF("flistxattr ( %d, %p, %d )\n", arg1, arg2, arg3);
1257 SYSCALL_TRACK( pre_mem_write, tid, "listxattr(list)", arg2, arg3 );
1258}
1259
1260POST(flistxattr)
1261{
1262 if (res > 0 && arg2 != (Addr)NULL)
1263 VG_TRACK( post_mem_write, arg2, res );
1264}
1265
1266PRE(removexattr)
1267{
1268 MAYBE_PRINTF("removexattr ( %p, %p )\n", arg1, arg2);
1269 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "listxattr(path)", arg1 );
1270 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "listxattr(name)", arg2 );
1271}
1272
1273PREALIAS(lremovexattr, removexattr);
1274
1275PRE(fremovexattr)
1276{
1277 MAYBE_PRINTF("removexattr ( %d, %p )\n", arg1, arg2);
1278 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "listxattr(name)", arg2 );
1279}
1280
1281PRE(quotactl)
1282{
1283 MAYBE_PRINTF("quotactl (0x%x, %p, 0x%x, 0x%x )\n",
1284 arg1,arg2,arg3, arg4);
1285 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "quotactl(special)", arg2 );
1286}
1287
1288PRE(lookup_dcookie)
1289{
1290 MAYBE_PRINTF("lookup_dcookie (0x%llx, %p, %d)\n",
1291 arg1 | ((long long) arg2 << 32), arg3, arg4);
1292 SYSCALL_TRACK( pre_mem_write, tid, "lookup_dcookie(buf)", arg3, arg4);
1293}
1294
1295POST(lookup_dcookie)
1296{
1297 if (arg3 != (Addr)NULL)
1298 VG_TRACK( post_mem_write, arg3, res);
1299}
1300
1301PRE(truncate64)
1302{
1303 MAYBE_PRINTF("truncate64 ( %p, %lld )\n",
1304 arg1, ((ULong)arg2) | (((ULong) arg3) << 32));
1305 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "truncate64(path)", arg1 );
1306}
1307
1308PRE(fdatasync)
1309{
1310 /* int fdatasync(int fd); */
1311 MAYBE_PRINTF("fdatasync ( %d )\n", arg1);
1312}
1313
1314PRE(msync)
1315{
1316 /* int msync(const void *start, size_t length, int flags); */
1317 MAYBE_PRINTF("msync ( %p, %d, %d )\n", arg1,arg2,arg3);
1318 SYSCALL_TRACK( pre_mem_read, tid, "msync(start)", arg1, arg2 );
1319}
1320
1321struct getpmsg_strbuf {
1322 int maxlen; /* no. of bytes in buffer */
1323 int len; /* no. of bytes returned */
1324 caddr_t buf; /* pointer to data */
1325};
1326
1327PRE(getpmsg)
1328{
1329 /* LiS getpmsg from http://www.gcom.com/home/linux/lis/ */
1330 /* int getpmsg(int fd, struct strbuf *ctrl, struct strbuf *data,
1331 int *bandp, int *flagsp); */
1332 struct getpmsg_strbuf *ctrl;
1333 struct getpmsg_strbuf *data;
1334 MAYBE_PRINTF("getpmsg ( %d, %p, %p, %p, %p )\n",
1335 arg1,arg2,arg3,arg4,arg5);
1336 ctrl = (struct getpmsg_strbuf *)arg2;
1337 data = (struct getpmsg_strbuf *)arg3;
1338 if (ctrl && ctrl->maxlen > 0)
1339 SYSCALL_TRACK( pre_mem_write,tid, "getpmsg(ctrl)",
nethercotea8c1e922004-10-26 10:57:24 +00001340 (Addr)ctrl->buf, ctrl->maxlen);
jsgf855d93d2003-10-13 22:26:55 +00001341 if (data && data->maxlen > 0)
1342 SYSCALL_TRACK( pre_mem_write,tid, "getpmsg(data)",
nethercotea8c1e922004-10-26 10:57:24 +00001343 (Addr)data->buf, data->maxlen);
jsgf855d93d2003-10-13 22:26:55 +00001344 if (arg4)
1345 SYSCALL_TRACK( pre_mem_write,tid, "getpmsg(bandp)",
nethercotea8c1e922004-10-26 10:57:24 +00001346 (Addr)arg4, sizeof(int));
jsgf855d93d2003-10-13 22:26:55 +00001347 if (arg5)
1348 SYSCALL_TRACK( pre_mem_write,tid, "getpmsg(flagsp)",
nethercotea8c1e922004-10-26 10:57:24 +00001349 (Addr)arg5, sizeof(int));
jsgf855d93d2003-10-13 22:26:55 +00001350}
1351
1352POST(getpmsg)
1353{
1354 struct getpmsg_strbuf *ctrl;
1355 struct getpmsg_strbuf *data;
1356
1357 ctrl = (struct getpmsg_strbuf *)arg2;
1358 data = (struct getpmsg_strbuf *)arg3;
1359 if (res == 0 && ctrl && ctrl->len > 0) {
nethercotea8c1e922004-10-26 10:57:24 +00001360 VG_TRACK( post_mem_write, (Addr)ctrl->buf, ctrl->len);
jsgf855d93d2003-10-13 22:26:55 +00001361 }
1362 if (res == 0 && data && data->len > 0) {
nethercotea8c1e922004-10-26 10:57:24 +00001363 VG_TRACK( post_mem_write, (Addr)data->buf, data->len);
jsgf855d93d2003-10-13 22:26:55 +00001364 }
1365}
1366
1367PRE(putpmsg)
1368{
1369 /* LiS putpmsg from http://www.gcom.com/home/linux/lis/ */
1370 /* int putpmsg(int fd, struct strbuf *ctrl, struct strbuf *data,
1371 int band, int flags); */
1372 struct strbuf {
1373 int maxlen; /* no. of bytes in buffer */
1374 int len; /* no. of bytes returned */
1375 caddr_t buf; /* pointer to data */
1376 };
1377 struct strbuf *ctrl;
1378 struct strbuf *data;
1379 MAYBE_PRINTF("putpmsg ( %d, %p, %p, %d, %d )\n",
1380 arg1,arg2,arg3,arg4,arg5);
1381 ctrl = (struct strbuf *)arg2;
1382 data = (struct strbuf *)arg3;
1383 if (ctrl && ctrl->len > 0)
1384 SYSCALL_TRACK( pre_mem_read,tid, "putpmsg(ctrl)",
nethercotea8c1e922004-10-26 10:57:24 +00001385 (Addr)ctrl->buf, ctrl->len);
jsgf855d93d2003-10-13 22:26:55 +00001386 if (data && data->len > 0)
1387 SYSCALL_TRACK( pre_mem_read,tid, "putpmsg(data)",
nethercotea8c1e922004-10-26 10:57:24 +00001388 (Addr)data->buf, data->len);
jsgf855d93d2003-10-13 22:26:55 +00001389}
1390
1391PRE(getitimer)
1392{
1393 /* int getitimer(int which, struct itimerval *value); */
1394 MAYBE_PRINTF("getitimer ( %d, %p )\n", arg1, arg2);
1395 SYSCALL_TRACK( pre_mem_write, tid, "getitimer(timer)", arg2,
1396 sizeof(struct itimerval) );
1397}
1398
1399POST(getitimer)
1400{
1401 if (arg2 != (Addr)NULL) {
1402 VG_TRACK( post_mem_write,arg2, sizeof(struct itimerval));
1403 }
1404}
1405
1406PRE(syslog)
1407{
1408 /* int syslog(int type, char *bufp, int len); */
1409 MAYBE_PRINTF("syslog (%d, %p, %d)\n",arg1,arg2,arg3);
1410 switch(arg1) {
1411 case 2: case 3: case 4:
1412 SYSCALL_TRACK( pre_mem_write, tid, "syslog(buf)", arg2, arg3);
1413 break;
1414 default:
1415 break;
1416 }
1417}
1418
1419POST(syslog)
1420{
1421 switch (arg1) {
1422 case 2: case 3: case 4:
1423 VG_TRACK( post_mem_write, arg2, arg3 );
1424 break;
1425 default:
1426 break;
1427 }
1428}
1429
1430PRE(personality)
1431{
1432 /* int personality(unsigned long persona); */
1433 MAYBE_PRINTF("personality ( %d )\n", arg1);
1434}
1435
1436PRE(chroot)
1437{
1438 /* int chroot(const char *path); */
1439 MAYBE_PRINTF("chroot ( %p )\n", arg1);
1440 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "chroot(path)", arg1 );
1441}
1442
1443PRE(madvise)
1444{
1445 /* int madvise(void *start, size_t length, int advice ); */
1446 MAYBE_PRINTF("madvise ( %p, %d, %d )\n", arg1,arg2,arg3);
1447}
1448
1449PRE(mremap)
1450{
nethercote27ea8bc2004-07-10 17:21:14 +00001451 // Nb: this is different to the glibc version described in the man pages,
1452 // which lacks the fifth 'new_address' argument.
jsgf855d93d2003-10-13 22:26:55 +00001453 /* void* mremap(void * old_address, size_t old_size,
fitzhardinge1a303042003-12-22 08:48:50 +00001454 size_t new_size, unsigned long flags, void * new_address); */
1455 MAYBE_PRINTF("mremap ( %p, %d, %d, 0x%x, %p )\n",
1456 arg1, arg2, arg3, arg4, arg5);
nethercote27ea8bc2004-07-10 17:21:14 +00001457
nethercote35122912004-10-18 17:00:30 +00001458 set_result( mremap_segment((Addr)arg1, arg2, (Addr)arg5, arg3, arg4, tid) );
jsgf855d93d2003-10-13 22:26:55 +00001459}
1460
1461PRE(nice)
1462{
1463 /* int nice(int inc); */
1464 MAYBE_PRINTF("nice ( %d )\n", arg1);
1465}
1466
1467PRE(setresgid32)
1468{
1469 /* int setresgid(gid_t rgid, gid_t egid, gid_t sgid); */
1470 MAYBE_PRINTF("setresgid32 ( %d, %d, %d )\n", arg1, arg2, arg3);
1471}
1472
1473PRE(setfsuid32)
1474{
1475 /* int setfsuid(uid_t fsuid); */
1476 MAYBE_PRINTF("setfsuid ( %d )\n", arg1);
1477}
1478
1479PRE(_sysctl)
1480{
1481 /* int _sysctl(struct __sysctl_args *args); */
1482 MAYBE_PRINTF("_sysctl ( %p )\n", arg1 );
1483 SYSCALL_TRACK( pre_mem_write, tid, "_sysctl(args)", arg1,
1484 sizeof(struct __sysctl_args) );
1485}
1486
1487POST(_sysctl)
1488{
1489 VG_TRACK( post_mem_write, arg1, sizeof(struct __sysctl_args) );
1490
1491}
1492
1493PRE(sched_getscheduler)
1494{
1495 /* int sched_getscheduler(pid_t pid); */
1496 MAYBE_PRINTF("sched_getscheduler ( %d )\n", arg1);
1497}
1498
1499PRE(sched_setscheduler)
1500{
1501 /* int sched_setscheduler(pid_t pid, int policy,
1502 const struct sched_param *p); */
1503 MAYBE_PRINTF("sched_setscheduler ( %d, %d, %p )\n",arg1,arg2,arg3);
1504 if (arg3 != (UInt)NULL)
1505 SYSCALL_TRACK( pre_mem_read, tid,
1506 "sched_setscheduler(struct sched_param *p)",
1507 arg3, sizeof(struct sched_param));
1508}
1509
1510PRE(mlock)
1511{
1512 /* int mlock(const void * addr, size_t len) */
1513 MAYBE_PRINTF("mlock ( %p, %d )\n", arg1, arg2);
1514}
1515
1516PRE(munlock)
1517{
1518 /* int munlock(const void * addr, size_t len) */
1519 MAYBE_PRINTF("munlock ( %p, %d )\n", arg1, arg2);
1520}
1521
1522PRE(mlockall)
1523{
1524 /* int mlockall(int flags); */
1525 MAYBE_PRINTF("mlockall ( %x )\n", arg1);
1526}
1527
1528PRE(munlockall)
1529{
nethercotee70bd7d2004-08-18 14:37:17 +00001530 /* int munlockall(void) */
1531 MAYBE_PRINTF("munlockall()\n");
jsgf855d93d2003-10-13 22:26:55 +00001532}
1533
1534PRE(sched_get_priority_max)
1535{
1536 /* int sched_get_priority_max(int policy); */
1537 MAYBE_PRINTF("sched_get_priority_max ( %d )\n", arg1);
1538}
1539
1540PRE(sched_get_priority_min)
1541{
1542 /* int sched_get_priority_min(int policy); */
1543 MAYBE_PRINTF("sched_get_priority_min ( %d )\n", arg1);
1544}
1545
1546PRE(setpriority)
1547{
1548 /* int setpriority(int which, int who, int prio); */
1549 MAYBE_PRINTF("setpriority ( %d, %d, %d )\n", arg1, arg2, arg3);
1550}
1551
1552PRE(getpriority)
1553{
1554 /* int getpriority(int which, int who); */
1555 MAYBE_PRINTF("getpriority ( %d, %d )\n", arg1, arg2);
1556}
1557
1558PRE(setfsgid)
1559{
1560 /* int setfsgid(gid_t gid); */
1561 MAYBE_PRINTF("setfsgid ( %d )\n", arg1);
1562}
1563
1564PRE(setregid)
1565{
1566 /* int setregid(gid_t rgid, gid_t egid); */
1567 MAYBE_PRINTF("setregid ( %d, %d )\n", arg1, arg2);
1568}
1569
1570PRE(setresuid)
1571{
1572 /* int setresuid(uid_t ruid, uid_t euid, uid_t suid); */
1573 MAYBE_PRINTF("setresuid ( %d, %d, %d )\n", arg1, arg2, arg3);
1574}
1575
1576PRE(setfsuid)
1577{
1578 /* int setfsuid(uid_t uid); */
1579 MAYBE_PRINTF("setfsuid ( %d )\n", arg1);
1580}
1581
1582PRE(sendfile)
1583{
1584 /* ssize_t sendfile(int out_fd, int in_fd, off_t *offset,
1585 size_t count) */
1586 MAYBE_PRINTF("sendfile ( %d, %d, %p, %d )\n",arg1,arg2,arg3,arg4);
1587 if (arg3 != (UInt)NULL)
1588 SYSCALL_TRACK( pre_mem_write, tid, "sendfile(offset)",
1589 arg3, sizeof(off_t) );
1590}
1591
1592POST(sendfile)
1593{
1594 VG_TRACK( post_mem_write, arg3, sizeof( off_t ) );
1595}
1596
1597PRE(sendfile64)
1598{
1599 /* ssize_t sendfile64(int out_df, int in_fd, loff_t *offset,
1600 size_t count); */
1601 MAYBE_PRINTF("sendfile64 ( %d, %d, %p, %d )\n",arg1,arg2,arg3,arg4);
1602 if (arg3 != (UInt)NULL)
1603 SYSCALL_TRACK( pre_mem_write, tid, "sendfile64(offset)",
1604 arg3, sizeof(loff_t) );
1605}
1606
1607POST(sendfile64)
1608{
1609 if (arg3 != (UInt)NULL ) {
1610 VG_TRACK( post_mem_write, arg3, sizeof(loff_t) );
1611 }
1612}
1613
1614PRE(pwrite64)
1615{
nethercotee70bd7d2004-08-18 14:37:17 +00001616 // ssize_t pwrite64(int fd, const void *buf, size_t nbytes, loff_t offset);
1617 MAYBE_PRINTF("pwrite64 ( %d, %p, %d, %lld )\n",
1618 arg1, arg2, arg3, arg4|((ULong) arg5 << 32));
1619 SYSCALL_TRACK( pre_mem_read, tid, "pwrite64(buf)", arg2, arg3 );
jsgf855d93d2003-10-13 22:26:55 +00001620}
1621
1622PRE(sync)
1623{
1624 /* int sync(); */
1625 MAYBE_PRINTF("sync ( )\n");
1626}
1627
1628PRE(fstatfs)
1629{
1630 /* int fstatfs(int fd, struct statfs *buf); */
1631 MAYBE_PRINTF("fstatfs ( %d, %p )\n",arg1,arg2);
1632 SYSCALL_TRACK( pre_mem_write, tid, "stat(buf)",
thughes66d80092004-06-19 12:41:05 +00001633 arg2, sizeof(struct vki_statfs) );
jsgf855d93d2003-10-13 22:26:55 +00001634}
1635
1636POST(fstatfs)
1637{
thughes66d80092004-06-19 12:41:05 +00001638 VG_TRACK( post_mem_write, arg2, sizeof(struct vki_statfs) );
jsgf855d93d2003-10-13 22:26:55 +00001639}
1640
thughesa996d3b2004-09-24 22:57:17 +00001641PRE(fstatfs64)
1642{
1643 /* int fstatfs64(int fd, size_t sz, struct statfs *buf); */
1644 MAYBE_PRINTF("fstatfs64 ( %d, %p )\n",arg1,arg2);
1645 SYSCALL_TRACK( pre_mem_write, tid, "stat(buf)", arg3, arg2 );
1646}
1647
1648POST(fstatfs64)
1649{
1650 VG_TRACK( post_mem_write, arg3, arg2 );
1651}
1652
jsgf855d93d2003-10-13 22:26:55 +00001653PRE(getsid)
1654{
1655 /* pid_t getsid(pid_t pid); */
1656 MAYBE_PRINTF("getsid ( %d )\n", arg1);
1657}
1658
1659PRE(pread64)
1660{
nethercotee70bd7d2004-08-18 14:37:17 +00001661 /* ssize_t pread64(int fd, void *buf, size_t count, loff_t offset); */
1662 MAYBE_PRINTF("pread ( %d, %p, %d, %lld )\n",
1663 arg1, arg2, arg3, arg4|((ULong) arg5 << 32));
jsgf855d93d2003-10-13 22:26:55 +00001664 SYSCALL_TRACK( pre_mem_write, tid, "pread(buf)", arg2, arg3 );
1665}
1666
1667POST(pread64)
1668{
1669 MAYBE_PRINTF("SYSCALL[%d] pread ( %d, %p, %d, %d ) --> %d\n",
1670 VG_(getpid)(),
1671 arg1, arg2, arg3, arg4, res);
1672 if (res > 0) {
1673 VG_TRACK( post_mem_write, arg2, res );
1674 }
1675}
1676
1677PRE(mknod)
1678{
1679 /* int mknod(const char *pathname, mode_t mode, dev_t dev); */
1680 MAYBE_PRINTF("mknod ( %p, 0x%x, 0x%x )\n", arg1, arg2, arg3 );
1681 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "mknod(pathname)", arg1 );
1682}
1683
1684PRE(flock)
1685{
1686 /* int flock(int fd, int operation); */
1687 MAYBE_PRINTF("flock ( %d, %d )\n", arg1, arg2 );
1688}
1689
1690PRE(init_module)
1691{
1692 /* int init_module(const char *name, struct module *image); */
1693 MAYBE_PRINTF("init_module ( %p, %p )\n", arg1, arg2 );
1694 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "init_module(name)", arg1 );
1695 SYSCALL_TRACK( pre_mem_read, tid, "init_module(image)", arg2,
1696 VKI_SIZEOF_STRUCT_MODULE );
1697}
1698
1699PRE(ioperm)
1700{
1701 /* int ioperm(unsigned long from, unsigned long num, int turn_on); */
1702 MAYBE_PRINTF("ioperm ( %d, %d, %d )\n", arg1, arg2, arg3 );
1703}
1704
1705PRE(capget)
1706{
1707 /* int capget(cap_user_header_t header, cap_user_data_t data); */
1708 MAYBE_PRINTF("capget ( %p, %p )\n", arg1, arg2 );
1709 SYSCALL_TRACK( pre_mem_read, tid, "capget(header)", arg1,
1710 sizeof(vki_cap_user_header_t) );
1711 SYSCALL_TRACK( pre_mem_write, tid, "capget(data)", arg2,
1712 sizeof( vki_cap_user_data_t) );
1713}
1714
1715POST(capget)
1716{
1717 if (arg2 != (Addr)NULL)
1718 VG_TRACK( post_mem_write, arg2, sizeof( vki_cap_user_data_t) );
1719}
1720
1721PRE(capset)
1722{
1723 SYSCALL_TRACK( pre_mem_read, tid, "capset(header)",
1724 arg1, sizeof(vki_cap_user_header_t) );
1725 SYSCALL_TRACK( pre_mem_read, tid, "capset(data)",
1726 arg2, sizeof( vki_cap_user_data_t) );
1727}
1728
nethercotea81e9162004-02-12 14:34:14 +00001729// Pre_read a char** argument.
1730void pre_argv_envp(Addr a, ThreadId tid, Char* s1, Char* s2)
1731{
1732 while (True) {
1733 Addr a_deref = deref_Addr( tid, a, s1 );
1734 if (0 == a_deref)
1735 break;
1736 SYSCALL_TRACK( pre_mem_read_asciiz, tid, s2, a_deref );
1737 a += sizeof(char*);
1738 }
1739}
1740
jsgf855d93d2003-10-13 22:26:55 +00001741PRE(execve)
1742{
1743 /* int execve (const char *filename,
1744 char *const argv [],
1745 char *const envp[]); */
nethercotea81e9162004-02-12 14:34:14 +00001746 MAYBE_PRINTF("execve ( %p(%s), %p, %p )\n", arg1, arg1, arg2, arg3);
1747
1748 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "execve(filename)", arg1 );
thughes7f72d012004-07-21 16:23:38 +00001749 if (arg2 != (UInt)NULL)
1750 pre_argv_envp( arg2, tid, "execve(argv)", "execve(argv[i])" );
thughes4b9e0152004-06-19 13:02:34 +00001751 if (arg3 != (UInt)NULL)
1752 pre_argv_envp( arg3, tid, "execve(envp)", "execve(envp[i])" );
fitzhardingee1c06d82003-10-30 07:21:44 +00001753
1754 /* Erk. If the exec fails, then the following will have made a
1755 mess of things which makes it hard for us to continue. The
1756 right thing to do is piece everything together again in
1757 POST(execve), but that's hard work. Instead, we make an effort
1758 to check that the execve will work before actually calling
1759 exec. */
1760 {
1761 struct vki_stat st;
1762 Int ret = VG_(stat)((Char *)arg1, &st);
1763
1764 if (ret < 0) {
nethercote35122912004-10-18 17:00:30 +00001765 set_result( ret );
fitzhardingee1c06d82003-10-30 07:21:44 +00001766 return;
1767 }
thughes90efa302004-09-25 16:13:55 +00001768 /* just look for regular file with any X bit set
fitzhardingee1c06d82003-10-30 07:21:44 +00001769 XXX do proper permissions check?
1770 */
thughes90efa302004-09-25 16:13:55 +00001771 if ((st.st_mode & 0100111) == 0100000) {
nethercote35122912004-10-18 17:00:30 +00001772 set_result( -VKI_EACCES );
fitzhardingee1c06d82003-10-30 07:21:44 +00001773 return;
1774 }
1775 }
1776
1777 /* Resistance is futile. Nuke all other threads. POSIX mandates
1778 this. (Really, nuke them all, since the new process will make
1779 its own new thread.) */
1780 VG_(nuke_all_threads_except)( VG_INVALID_THREADID );
1781
fitzhardinge5408c062004-01-04 23:52:59 +00001782 {
nethercote60a96c52004-08-03 13:08:31 +00001783 // Remove the valgrind-specific stuff from the environment so the
1784 // child doesn't get our libpthread and other stuff. This is
1785 // done unconditionally, since if we are tracing the child,
1786 // stage1/2 will set up the appropriate client environment.
jsgf855d93d2003-10-13 22:26:55 +00001787 Char** envp = (Char**)arg3;
fitzhardinge98abfc72003-12-16 02:05:15 +00001788
1789 if (envp != NULL) {
nethercote60a96c52004-08-03 13:08:31 +00001790 VG_(env_remove_valgrind_env_stuff)( envp );
jsgf855d93d2003-10-13 22:26:55 +00001791 }
fitzhardinge5408c062004-01-04 23:52:59 +00001792 }
1793
1794 if (VG_(clo_trace_children)) {
nethercotef6a1d502004-08-09 12:21:57 +00001795 Char* optvar = VG_(build_child_VALGRINDCLO)( (Char*)arg1 );
fitzhardinge98abfc72003-12-16 02:05:15 +00001796
nethercotef6a1d502004-08-09 12:21:57 +00001797 // Set VALGRINDCLO and VALGRINDLIB in arg3 (the environment)
1798 VG_(env_setenv)( (Char***)&arg3, VALGRINDCLO, optvar);
1799 VG_(env_setenv)( (Char***)&arg3, VALGRINDLIB, VG_(libdir));
fitzhardinge98abfc72003-12-16 02:05:15 +00001800
nethercotef6a1d502004-08-09 12:21:57 +00001801 // Create executable name: "/proc/self/fd/<vgexecfd>", update arg1
nethercotea8c1e922004-10-26 10:57:24 +00001802 arg1 = (Addr)VG_(build_child_exename)();
fitzhardinge98abfc72003-12-16 02:05:15 +00001803 }
1804
1805 if (0) {
1806 Char **cpp;
1807
1808 VG_(printf)("exec: %s\n", (Char *)arg1);
1809 for(cpp = (Char **)arg2; cpp && *cpp; cpp++)
nethercotef6a1d502004-08-09 12:21:57 +00001810 VG_(printf)("argv: %s\n", *cpp);
fitzhardinge98abfc72003-12-16 02:05:15 +00001811 for(cpp = (Char **)arg3; cpp && *cpp; cpp++)
nethercotef6a1d502004-08-09 12:21:57 +00001812 VG_(printf)("env: %s\n", *cpp);
jsgf855d93d2003-10-13 22:26:55 +00001813 }
jsgf855d93d2003-10-13 22:26:55 +00001814
fitzhardingef0dd7e12004-01-16 02:17:30 +00001815 /* Set our real sigmask to match the client's sigmask so that the
1816 exec'd child will get the right mask. First we need to clear
1817 out any pending signals so they they don't get delivered, which
1818 would confuse things.
1819
1820 XXX This is a bug - the signals should remain pending, and be
1821 delivered to the new process after exec. There's also a
1822 race-condition, since if someone delivers us a signal between
1823 the sigprocmask and the execve, we'll still get the signal. Oh
1824 well.
1825 */
1826 {
1827 vki_ksigset_t allsigs;
1828 vki_ksiginfo_t info;
1829 static const struct vki_timespec zero = { 0, 0 };
1830
1831 VG_(ksigfillset)(&allsigs);
1832 while(VG_(ksigtimedwait)(&allsigs, &info, &zero) > 0)
1833 ;
1834
1835 VG_(ksigprocmask)(VKI_SIG_SETMASK, &tst->sig_mask, NULL);
1836 }
1837
fitzhardingeb50068f2004-02-24 23:42:55 +00001838 /* restore the DATA rlimit for the child */
1839 VG_(setrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
1840
nethercote35122912004-10-18 17:00:30 +00001841 set_result( VG_(do_syscall)(__NR_execve, arg1, arg2, arg3) );
fitzhardingee1c06d82003-10-30 07:21:44 +00001842
1843 /* If we got here, then the execve failed. We've already made too much of a mess
1844 of ourselves to continue, so we have to abort. */
nethercotee70bd7d2004-08-18 14:37:17 +00001845 VG_(message)(Vg_UserMsg, "execve(%p(%s), %p, %p) failed, errno %d",
fitzhardingee1c06d82003-10-30 07:21:44 +00001846 arg1, arg1, arg2, arg3, -res);
1847 VG_(core_panic)("EXEC FAILED: I can't recover from execve() failing, so I'm dying.\n"
1848 "Add more stringent tests in PRE(execve), or work out how to recover.");
jsgf855d93d2003-10-13 22:26:55 +00001849}
1850
1851PRE(access)
1852{
1853 /* int access(const char *pathname, int mode); */
thughes8ba345e2004-08-26 12:26:27 +00001854 MAYBE_PRINTF("access ( %p(%s), %d )\n", arg1,arg1,arg2);
jsgf855d93d2003-10-13 22:26:55 +00001855 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "access(pathname)", arg1 );
1856}
1857
1858PRE(alarm)
1859{
1860 /* unsigned int alarm(unsigned int seconds); */
1861 MAYBE_PRINTF("alarm ( %d )\n", arg1);
1862}
1863
1864PRE(brk)
1865{
fitzhardinge98abfc72003-12-16 02:05:15 +00001866 Addr brk_limit = VG_(brk_limit);
1867
jsgf855d93d2003-10-13 22:26:55 +00001868 /* libc says: int brk(void *end_data_segment);
1869 kernel says: void* brk(void* end_data_segment); (more or less)
1870
1871 libc returns 0 on success, and -1 (and sets errno) on failure.
1872 Nb: if you ask to shrink the dataseg end below what it
1873 currently is, that always succeeds, even if the dataseg end
1874 doesn't actually change (eg. brk(0)). Unless it seg faults.
1875
1876 Kernel returns the new dataseg end. If the brk() failed, this
1877 will be unchanged from the old one. That's why calling (kernel)
1878 brk(0) gives the current dataseg end (libc brk() just returns
1879 zero in that case).
1880
1881 Both will seg fault if you shrink it back into a text segment.
1882 */
1883 MAYBE_PRINTF("brk ( %p ) --> ",arg1);
jsgf855d93d2003-10-13 22:26:55 +00001884
nethercote35122912004-10-18 17:00:30 +00001885 set_result( do_brk(arg1) );
fitzhardinge98abfc72003-12-16 02:05:15 +00001886
jsgf855d93d2003-10-13 22:26:55 +00001887 MAYBE_PRINTF("0x%x\n", res);
1888
1889 if (res == arg1) {
1890 /* brk() succeeded */
fitzhardinge98abfc72003-12-16 02:05:15 +00001891 if (res < brk_limit) {
jsgf855d93d2003-10-13 22:26:55 +00001892 /* successfully shrunk the data segment. */
1893 VG_TRACK( die_mem_brk, (Addr)arg1,
fitzhardinge98abfc72003-12-16 02:05:15 +00001894 brk_limit-arg1 );
jsgf855d93d2003-10-13 22:26:55 +00001895 } else
fitzhardinge98abfc72003-12-16 02:05:15 +00001896 if (res > brk_limit) {
jsgf855d93d2003-10-13 22:26:55 +00001897 /* successfully grew the data segment */
fitzhardinge98abfc72003-12-16 02:05:15 +00001898 VG_TRACK( new_mem_brk, brk_limit,
1899 arg1-brk_limit );
jsgf855d93d2003-10-13 22:26:55 +00001900 }
jsgf855d93d2003-10-13 22:26:55 +00001901 } else {
1902 /* brk() failed */
fitzhardinge98abfc72003-12-16 02:05:15 +00001903 vg_assert(brk_limit == res);
jsgf855d93d2003-10-13 22:26:55 +00001904 }
1905}
1906
1907PRE(chdir)
1908{
1909 /* int chdir(const char *path); */
1910 MAYBE_PRINTF("chdir ( %p )\n", arg1);
1911 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "chdir(path)", arg1 );
1912}
1913
1914PRE(chmod)
1915{
1916 /* int chmod(const char *path, mode_t mode); */
1917 MAYBE_PRINTF("chmod ( %p, %d )\n", arg1,arg2);
1918 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "chmod(path)", arg1 );
1919}
1920
1921PRE(chown)
1922{
1923 /* int chown(const char *path, uid_t owner, gid_t group); */
1924 MAYBE_PRINTF("chown ( %p, 0x%x, 0x%x )\n", arg1,arg2,arg3);
1925 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "chown(path)", arg1 );
1926}
1927
1928PREALIAS(chown32, chown);
1929PREALIAS(lchown32, chown);
1930
1931PRE(close)
1932{
1933 /* int close(int fd); */
1934 MAYBE_PRINTF("close ( %d )\n",arg1);
nethercotef8548672004-06-21 12:42:35 +00001935 /* Detect and negate attempts by the client to close Valgrind's log fd */
thughesad1c9562004-06-26 11:27:52 +00001936 if (!fd_allowed(arg1, "close", tid, False))
nethercote35122912004-10-18 17:00:30 +00001937 set_result( -VKI_EBADF );
jsgf855d93d2003-10-13 22:26:55 +00001938}
1939
rjwalshf5f536f2003-11-17 17:45:00 +00001940POST(close)
1941{
1942 if(VG_(clo_track_fds)) record_fd_close(tid, arg1);
1943}
jsgf855d93d2003-10-13 22:26:55 +00001944
1945PRE(dup)
1946{
1947 /* int dup(int oldfd); */
1948 MAYBE_PRINTF("dup ( %d ) --> ", arg1);
1949}
1950
1951POST(dup)
1952{
1953 MAYBE_PRINTF("%d\n", res);
thughesad1c9562004-06-26 11:27:52 +00001954 if (!fd_allowed(res, "dup", tid, True)) {
jsgf855d93d2003-10-13 22:26:55 +00001955 VG_(close)(res);
nethercote35122912004-10-18 17:00:30 +00001956 set_result( -VKI_EMFILE );
rjwalshf5f536f2003-11-17 17:45:00 +00001957 } else {
1958 if(VG_(clo_track_fds))
fitzhardinge98abfc72003-12-16 02:05:15 +00001959 record_fd_open(tid, res, VG_(resolve_filename)(res));
jsgf855d93d2003-10-13 22:26:55 +00001960 }
1961}
1962
1963PRE(dup2)
1964{
1965 /* int dup2(int oldfd, int newfd); */
1966 MAYBE_PRINTF("dup2 ( %d, %d ) ...\n", arg1,arg2);
thughesad1c9562004-06-26 11:27:52 +00001967 if (!fd_allowed(arg2, "dup2", tid, True))
nethercote35122912004-10-18 17:00:30 +00001968 set_result( -VKI_EBADF );
jsgf855d93d2003-10-13 22:26:55 +00001969}
1970
1971POST(dup2)
1972{
1973 MAYBE_PRINTF("SYSCALL[%d] dup2 ( %d, %d ) = %d\n",
1974 VG_(getpid)(),
1975 arg1, arg2, res);
rjwalshf5f536f2003-11-17 17:45:00 +00001976 if(VG_(clo_track_fds))
fitzhardinge98abfc72003-12-16 02:05:15 +00001977 record_fd_open(tid, res, VG_(resolve_filename)(res));
jsgf855d93d2003-10-13 22:26:55 +00001978}
1979
1980PRE(fcntl)
1981{
1982 /* int fcntl(int fd, int cmd, int arg); */
1983 MAYBE_PRINTF("fcntl ( %d, %d, %d )\n",arg1,arg2,arg3);
thughesd4b51a62004-07-29 21:20:11 +00001984 if (arg2 == VKI_F_SETLKW)
1985 tst->sys_flags |= MayBlock;
jsgf855d93d2003-10-13 22:26:55 +00001986}
1987
rjwalshf5f536f2003-11-17 17:45:00 +00001988POST(fcntl)
1989{
nethercote493dd182004-02-24 23:57:47 +00001990 if (arg2 == VKI_F_DUPFD) {
thughesad1c9562004-06-26 11:27:52 +00001991 if (!fd_allowed(res, "fcntl(DUPFD)", tid, True)) {
nethercote493dd182004-02-24 23:57:47 +00001992 VG_(close)(res);
nethercote35122912004-10-18 17:00:30 +00001993 set_result( -VKI_EMFILE );
nethercote493dd182004-02-24 23:57:47 +00001994 } else {
1995 if (VG_(clo_track_fds))
1996 record_fd_open(tid, res, VG_(resolve_filename)(res));
1997 }
1998 }
rjwalshf5f536f2003-11-17 17:45:00 +00001999}
2000
jsgf855d93d2003-10-13 22:26:55 +00002001PRE(fchdir)
2002{
2003 /* int fchdir(int fd); */
2004 MAYBE_PRINTF("fchdir ( %d )\n", arg1);
2005}
2006
2007PRE(fchown)
2008{
2009 /* int fchown(int filedes, uid_t owner, gid_t group); */
2010 MAYBE_PRINTF("fchown ( %d, %d, %d )\n", arg1,arg2,arg3);
2011}
2012
2013PREALIAS(fchown32, fchown);
2014
2015PRE(fchmod)
2016{
2017 /* int fchmod(int fildes, mode_t mode); */
2018 MAYBE_PRINTF("fchmod ( %d, %d )\n", arg1,arg2);
2019}
2020
2021PRE(fcntl64)
2022{
rjwalshf5f536f2003-11-17 17:45:00 +00002023 /* int fcntl64(int fd, int cmd, int arg); */
2024 MAYBE_PRINTF("fcntl64 ( %d, %d, %d )\n", arg1,arg2,arg3);
thughesd4b51a62004-07-29 21:20:11 +00002025 if (arg2 == VKI_F_SETLKW || arg2 == VKI_F_SETLKW64)
2026 tst->sys_flags |= MayBlock;
rjwalshf5f536f2003-11-17 17:45:00 +00002027}
2028
2029POST(fcntl64)
2030{
nethercote493dd182004-02-24 23:57:47 +00002031 if (arg2 == VKI_F_DUPFD) {
thughesad1c9562004-06-26 11:27:52 +00002032 if (!fd_allowed(res, "fcntl64(DUPFD)", tid, True)) {
nethercote493dd182004-02-24 23:57:47 +00002033 VG_(close)(res);
nethercote35122912004-10-18 17:00:30 +00002034 set_result( -VKI_EMFILE );
nethercote493dd182004-02-24 23:57:47 +00002035 } else {
2036 if (VG_(clo_track_fds))
2037 record_fd_open(tid, res, VG_(resolve_filename)(res));
2038 }
2039 }
jsgf855d93d2003-10-13 22:26:55 +00002040}
2041
2042PRE(fstat)
2043{
2044 /* int fstat(int filedes, struct stat *buf); */
2045 MAYBE_PRINTF("fstat ( %d, %p )\n",arg1,arg2);
2046 SYSCALL_TRACK( pre_mem_write, tid, "fstat", arg2, sizeof(struct stat) );
2047}
2048
2049POST(fstat)
2050{
2051 VG_TRACK( post_mem_write, arg2, sizeof(struct stat) );
2052}
2053
2054static vki_ksigset_t fork_saved_mask;
2055
2056PRE(fork)
2057{
2058 vki_ksigset_t mask;
2059
2060 vg_assert(VG_(gettid)() == VG_(main_pid));
2061
2062 /* Block all signals during fork, so that we can fix things up in
2063 the child without being interrupted. */
2064 VG_(ksigfillset)(&mask);
2065 VG_(ksigprocmask)(VKI_SIG_SETMASK, &mask, &fork_saved_mask);
2066
2067 /* pid_t fork(void); */
2068 MAYBE_PRINTF("fork ()\n");
2069
2070 do_atfork_pre(tid);
2071}
2072
2073POST(fork)
2074{
2075 if (res == 0) {
2076 do_atfork_child(tid);
2077
2078 /* I am the child. Nuke all other threads which I might
2079 have inherited from my parent. POSIX mandates this. */
2080 VG_(nuke_all_threads_except)( tid );
2081
2082 /* XXX TODO: tid 1 is special, and is presumed to be present.
2083 We should move this TID to 1 in the child. */
2084
2085 /* restore signal mask */
2086 VG_(ksigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
2087 } else {
2088 MAYBE_PRINTF(" fork: process %d created child %d\n", VG_(main_pid), res);
2089
2090 do_atfork_parent(tid);
2091
2092 /* restore signal mask */
2093 VG_(ksigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
2094 }
2095}
2096
fitzhardinge47735af2004-01-21 01:27:27 +00002097PRE(clone)
2098{
2099 MAYBE_PRINTF("clone ( %d, %p, %p, %p, %p )\n",arg1,arg2,arg3,arg4,arg5);
2100
2101 if (arg2 == 0 &&
nethercotea3d718e2004-02-15 16:15:05 +00002102 (arg1 == (VKI_CLONE_CHILD_CLEARTID|VKI_CLONE_CHILD_SETTID|VKI_SIGCHLD)
2103 || arg1 == (VKI_CLONE_PARENT_SETTID|VKI_SIGCHLD)))
2104 {
fitzhardinge47735af2004-01-21 01:27:27 +00002105 before_fork(tid, tst);
nethercote35122912004-10-18 17:00:30 +00002106 set_result( VG_(do_syscall)(SYSNO, arg1, arg2, arg3, arg4, arg5) );
fitzhardinge47735af2004-01-21 01:27:27 +00002107 after_fork(tid, tst);
2108 } else {
2109 VG_(unimplemented)
2110 ("clone(): not supported by Valgrind.\n "
2111 "We do now support programs linked against\n "
2112 "libpthread.so, though. Re-run with -v and ensure that\n "
2113 "you are picking up Valgrind's implementation of libpthread.so.");
2114 }
2115}
2116
jsgf855d93d2003-10-13 22:26:55 +00002117PRE(fsync)
2118{
2119 /* int fsync(int fd); */
2120 MAYBE_PRINTF("fsync ( %d )\n", arg1);
2121}
2122
2123PRE(ftruncate)
2124{
2125 /* int ftruncate(int fd, size_t length); */
2126 MAYBE_PRINTF("ftruncate ( %d, %d )\n", arg1,arg2);
2127}
2128
2129PRE(ftruncate64)
2130{
2131 /* int ftruncate64(int fd, off64_t length); */
2132 MAYBE_PRINTF("ftruncate64 ( %d, %lld )\n",
2133 arg1,arg2|((long long) arg3 << 32));
2134}
2135
2136PRE(getdents)
2137{
2138 /* int getdents(unsigned int fd, struct dirent *dirp,
2139 unsigned int count); */
2140 MAYBE_PRINTF("getdents ( %d, %p, %d )\n",arg1,arg2,arg3);
2141 SYSCALL_TRACK( pre_mem_write, tid, "getdents(dirp)", arg2, arg3 );
2142}
2143
2144POST(getdents)
2145{
2146 if (res > 0)
2147 VG_TRACK( post_mem_write, arg2, res );
2148}
2149
2150PRE(getdents64)
2151{
2152 /* int getdents(unsigned int fd, struct dirent64 *dirp,
2153 unsigned int count); */
2154 MAYBE_PRINTF("getdents64 ( %d, %p, %d )\n",arg1,arg2,arg3);
2155 SYSCALL_TRACK( pre_mem_write, tid, "getdents64(dirp)", arg2, arg3 );
2156}
2157
2158POST(getdents64)
2159{
2160 if (res > 0)
2161 VG_TRACK( post_mem_write, arg2, res );
2162}
2163
2164PRE(getgroups)
2165{
2166 /* int getgroups(int size, gid_t list[]); */
2167 MAYBE_PRINTF("getgroups ( %d, %p )\n", arg1, arg2);
2168 if (arg1 > 0)
2169 SYSCALL_TRACK( pre_mem_write, tid, "getgroups(list)", arg2,
2170 arg1 * sizeof(gid_t) );
2171}
2172
2173POST(getgroups)
2174{
2175 if (arg1 > 0 && res > 0)
2176 VG_TRACK( post_mem_write, arg2, res * sizeof(gid_t) );
2177}
2178
2179PREALIAS(getgroups32, getgroups);
2180POSTALIAS(getgroups32, getgroups);
2181
2182PRE(getcwd)
2183{
nethercotee70bd7d2004-08-18 14:37:17 +00002184 // Note that this prototype is the kernel one, with a different return
2185 // type to the glibc one!
2186 /* long getcwd(char *buf, size_t size); */
jsgf855d93d2003-10-13 22:26:55 +00002187 MAYBE_PRINTF("getcwd ( %p, %d )\n",arg1,arg2);
2188 SYSCALL_TRACK( pre_mem_write, tid, "getcwd(buf)", arg1, arg2 );
2189}
2190
2191POST(getcwd)
2192{
2193 if (res != (Addr)NULL)
2194 VG_TRACK( post_mem_write, arg1, res );
2195}
2196
2197PRE(geteuid)
2198{
2199 /* uid_t geteuid(void); */
2200 MAYBE_PRINTF("geteuid ( )\n");
2201}
2202
2203PRE(geteuid32)
2204{
2205 /* ?? uid_t geteuid32(void); */
2206 MAYBE_PRINTF("geteuid32(?) ( )\n");
2207}
2208
2209PRE(getegid)
2210{
2211 /* gid_t getegid(void); */
2212 MAYBE_PRINTF("getegid ()\n");
2213}
2214
2215PRE(getegid32)
2216{
2217 /* gid_t getegid32(void); */
2218 MAYBE_PRINTF("getegid32 ()\n");
2219}
2220
2221PRE(getgid)
2222{
2223 /* gid_t getgid(void); */
2224 MAYBE_PRINTF("getgid ()\n");
2225}
2226
2227PRE(getgid32)
2228{
2229 /* gid_t getgid32(void); */
2230 MAYBE_PRINTF("getgid32 ()\n");
2231}
2232
2233PRE(getpid)
2234{
2235 /* pid_t getpid(void); */
2236 MAYBE_PRINTF("getpid ()\n");
2237}
2238
2239PRE(getpgid)
2240{
2241 /* pid_t getpgid(pid_t pid); */
2242 MAYBE_PRINTF("getpgid ( %d )\n", arg1);
2243}
2244
2245PRE(getpgrp)
2246{
2247 /* pid_t getpgrp(void); */
2248 MAYBE_PRINTF("getpgrp ()\n");
2249}
2250
2251PRE(getppid)
2252{
2253 /* pid_t getppid(void); */
2254 MAYBE_PRINTF("getppid ()\n");
2255}
2256
2257PRE(getresgid)
2258{
2259 /* int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); */
2260 MAYBE_PRINTF("getresgid ( %p, %p, %p )\n", arg1,arg2,arg3);
2261 SYSCALL_TRACK( pre_mem_write, tid, "getresgid(rgid)",
2262 arg1, sizeof(gid_t) );
2263 SYSCALL_TRACK( pre_mem_write, tid, "getresgid(egid)",
2264 arg2, sizeof(gid_t) );
2265 SYSCALL_TRACK( pre_mem_write, tid, "getresgid(sgid)",
2266 arg3, sizeof(gid_t) );
2267}
2268
2269POST(getresgid)
2270{
2271 if (res == 0) {
2272 VG_TRACK( post_mem_write, arg1, sizeof(gid_t) );
2273 VG_TRACK( post_mem_write, arg2, sizeof(gid_t) );
2274 VG_TRACK( post_mem_write, arg3, sizeof(gid_t) );
2275 }
2276}
2277
2278PRE(getresgid32)
2279{
2280 /* int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); */
2281 MAYBE_PRINTF("getresgid32 ( %p, %p, %p )\n", arg1,arg2,arg3);
2282 SYSCALL_TRACK( pre_mem_write, tid, "getresgid32(rgid)",
2283 arg1, sizeof(gid_t) );
2284 SYSCALL_TRACK( pre_mem_write, tid, "getresgid32(egid)",
2285 arg2, sizeof(gid_t) );
2286 SYSCALL_TRACK( pre_mem_write, tid, "getresgid32(sgid)",
2287 arg3, sizeof(gid_t) );
2288}
2289
2290POST(getresgid32)
2291{
2292 if (res == 0) {
2293 VG_TRACK( post_mem_write, arg1, sizeof(gid_t) );
2294 VG_TRACK( post_mem_write, arg2, sizeof(gid_t) );
2295 VG_TRACK( post_mem_write, arg3, sizeof(gid_t) );
2296 }
2297}
2298
2299PRE(getresuid)
2300{
2301 /* int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); */
2302 MAYBE_PRINTF("getresuid ( %p, %p, %p )\n", arg1,arg2,arg3);
2303 SYSCALL_TRACK( pre_mem_write, tid, "getresuid(ruid)",
2304 arg1, sizeof(uid_t) );
2305 SYSCALL_TRACK( pre_mem_write, tid, "getresuid(euid)",
2306 arg2, sizeof(uid_t) );
2307 SYSCALL_TRACK( pre_mem_write, tid, "getresuid(suid)",
2308 arg3, sizeof(uid_t) );
2309}
2310
2311POST(getresuid)
2312{
2313 if (res == 0) {
2314 VG_TRACK( post_mem_write, arg1, sizeof(uid_t) );
2315 VG_TRACK( post_mem_write, arg2, sizeof(uid_t) );
2316 VG_TRACK( post_mem_write, arg3, sizeof(uid_t) );
2317 }
2318}
2319
2320PRE(getresuid32)
2321{
2322 /* int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); */
2323 MAYBE_PRINTF("getresuid32 ( %p, %p, %p )\n", arg1,arg2,arg3);
2324 SYSCALL_TRACK( pre_mem_write, tid, "getresuid32(ruid)",
2325 arg1, sizeof(uid_t) );
2326 SYSCALL_TRACK( pre_mem_write, tid, "getresuid32(euid)",
2327 arg2, sizeof(uid_t) );
2328 SYSCALL_TRACK( pre_mem_write, tid, "getresuid32(suid)",
2329 arg3, sizeof(uid_t) );
2330}
2331
2332POST(getresuid32)
2333{
2334 if (res == 0) {
2335 VG_TRACK( post_mem_write, arg1, sizeof(uid_t) );
2336 VG_TRACK( post_mem_write, arg2, sizeof(uid_t) );
2337 VG_TRACK( post_mem_write, arg3, sizeof(uid_t) );
2338 }
2339}
2340
2341PRE(getrlimit)
2342{
2343 /* int getrlimit (int resource, struct rlimit *rlim); */
2344 MAYBE_PRINTF("getrlimit ( %d, %p )\n", arg1,arg2);
2345 SYSCALL_TRACK( pre_mem_write, tid, "getrlimit(rlim)", arg2,
fitzhardingeb50068f2004-02-24 23:42:55 +00002346 sizeof(struct vki_rlimit) );
jsgf855d93d2003-10-13 22:26:55 +00002347}
2348
2349POST(getrlimit)
2350{
fitzhardingeb50068f2004-02-24 23:42:55 +00002351 VG_TRACK( post_mem_write, arg2, sizeof(struct vki_rlimit) );
nethercote535f03b2004-02-15 15:32:51 +00002352
fitzhardingeb50068f2004-02-24 23:42:55 +00002353 switch(arg1) {
2354 case VKI_RLIMIT_NOFILE:
thughesad1c9562004-06-26 11:27:52 +00002355 ((vki_rlimit *)arg2)->rlim_cur = VG_(fd_soft_limit);
2356 ((vki_rlimit *)arg2)->rlim_max = VG_(fd_hard_limit);
fitzhardingeb50068f2004-02-24 23:42:55 +00002357 break;
2358
2359 case VKI_RLIMIT_DATA:
2360 *((vki_rlimit *)arg2) = VG_(client_rlimit_data);
2361 break;
thughesc37184f2004-09-11 14:16:57 +00002362
2363 case VKI_RLIMIT_STACK:
2364 *((vki_rlimit *)arg2) = VG_(client_rlimit_stack);
2365 break;
fitzhardingeb50068f2004-02-24 23:42:55 +00002366 }
jsgf855d93d2003-10-13 22:26:55 +00002367}
2368
2369PREALIAS(ugetrlimit, getrlimit);
2370POSTALIAS(ugetrlimit, getrlimit);
2371
2372PRE(getrusage)
2373{
2374 /* int getrusage (int who, struct rusage *usage); */
2375 MAYBE_PRINTF("getrusage ( %d, %p )\n", arg1,arg2);
2376 SYSCALL_TRACK( pre_mem_write, tid, "getrusage(usage)", arg2,
2377 sizeof(struct rusage) );
2378}
2379
2380POST(getrusage)
2381{
2382 if (res == 0)
2383 VG_TRACK( post_mem_write,arg2, sizeof(struct rusage) );
2384}
2385
2386PRE(gettimeofday)
2387{
2388 /* int gettimeofday(struct timeval *tv, struct timezone *tz); */
2389 MAYBE_PRINTF("gettimeofday ( %p, %p )\n",arg1,arg2);
2390 SYSCALL_TRACK( pre_mem_write, tid, "gettimeofday(tv)", arg1,
2391 sizeof(struct timeval) );
2392 if (arg2 != 0)
2393 SYSCALL_TRACK( pre_mem_write, tid, "gettimeofday(tz)", arg2,
2394 sizeof(struct timezone) );
2395}
2396
2397POST(gettimeofday)
2398{
2399 if (res == 0) {
2400 VG_TRACK( post_mem_write, arg1, sizeof(struct timeval) );
2401 if (arg2 != 0)
2402 VG_TRACK( post_mem_write, arg2, sizeof(struct timezone) );
2403 }
2404}
2405
2406PRE(getuid)
2407{
2408 /* uid_t getuid(void); */
2409 MAYBE_PRINTF("getuid ( )\n");
2410}
2411
2412PRE(getuid32)
2413{
2414 /* ???uid_t getuid32(void); */
2415 MAYBE_PRINTF("getuid32 ( )\n");
2416}
2417
2418PRE(ipc)
2419{
2420 MAYBE_PRINTF("ipc ( %d, %d, %d, %d, %p, %d )\n",
2421 arg1,arg2,arg3,arg4,arg5,arg6);
2422 switch (arg1 /* call */) {
2423 case 1: /* IPCOP_semop */
2424 SYSCALL_TRACK( pre_mem_read, tid, "semop(sops)", arg5,
2425 arg3 * sizeof(struct sembuf) );
thughes024f25d2004-07-29 22:40:07 +00002426 tst->sys_flags |= MayBlock;
jsgf855d93d2003-10-13 22:26:55 +00002427 break;
2428 case 2: /* IPCOP_semget */
jsgf855d93d2003-10-13 22:26:55 +00002429 break;
thughes60797102004-08-13 22:21:51 +00002430 case 3: /* IPCOP_semctl */
2431 {
2432 union semun *arg = (union semun *)arg5;
2433 switch (arg4 /* cmd */) {
2434 case IPC_INFO:
2435 case SEM_INFO:
2436 {
2437 Addr buf = deref_Addr( tid, (Addr)&arg->__buf, "semctl(IPC_INFO, arg)" );
2438 SYSCALL_TRACK( pre_mem_write, tid, "semctl(IPC_INFO, arg->buf)", buf,
2439 sizeof(struct seminfo) );
2440 break;
2441 }
2442 case IPC_STAT:
2443 case SEM_STAT:
2444 {
2445 Addr buf = deref_Addr( tid, (Addr)&arg->buf, "semctl(IPC_STAT, arg)" );
2446 SYSCALL_TRACK( pre_mem_write, tid, "semctl(IPC_STAT, arg->buf)", buf,
2447 sizeof(struct semid_ds) );
2448 break;
2449 }
2450 case IPC_SET:
2451 {
2452 Addr buf = deref_Addr( tid, (Addr)&arg->buf, "semctl(IPC_SET, arg)" );
2453 SYSCALL_TRACK( pre_mem_read, tid, "semctl(IPC_SET, arg->buf)", buf,
2454 sizeof(struct semid_ds) );
2455 break;
2456 }
2457 case GETALL:
2458 {
2459 Addr array = deref_Addr( tid, (Addr)&arg->array, "semctl(IPC_GETALL, arg)" );
2460 UInt nsems = get_sem_count( arg2 );
2461 SYSCALL_TRACK( pre_mem_write, tid, "semctl(IPC_GETALL, arg->array)", array,
2462 sizeof(short) * nsems );
2463 break;
2464 }
2465 case SETALL:
2466 {
2467 Addr array = deref_Addr( tid, (Addr)&arg->array, "semctl(IPC_SETALL, arg)" );
2468 UInt nsems = get_sem_count( arg2 );
2469 SYSCALL_TRACK( pre_mem_read, tid, "semctl(IPC_SETALL, arg->array)", array,
2470 sizeof(short) * nsems );
2471 break;
2472 }
2473 case SETVAL:
2474 {
2475 SYSCALL_TRACK( pre_mem_read, tid, "semctl(IPC_SETVAL, arg->array)",
2476 (Addr)&arg->val, sizeof(arg->val) );
2477 break;
2478 }
2479# if defined(IPC_64)
2480 case IPC_INFO|IPC_64:
2481 case SEM_INFO|IPC_64:
2482 {
2483 Addr buf = deref_Addr( tid, (Addr)&arg->__buf, "semctl(IPC_INFO, arg)" );
2484 SYSCALL_TRACK( pre_mem_write, tid, "semctl(IPC_INFO, arg->buf)", buf,
2485 sizeof(struct seminfo) );
2486 break;
2487 }
2488 case IPC_STAT|IPC_64:
2489 case SEM_STAT|IPC_64:
2490 {
2491 Addr buf = deref_Addr( tid, (Addr)&arg->buf, "semctl(IPC_STAT, arg)" );
2492 SYSCALL_TRACK( pre_mem_write, tid, "semctl(IPC_STAT, arg->buf)", buf,
2493 sizeof(struct semid64_ds) );
2494 break;
2495 }
2496 case IPC_SET|IPC_64:
2497 {
2498 Addr buf = deref_Addr( tid, (Addr)&arg->buf, "semctl(IPC_SET, arg)" );
2499 SYSCALL_TRACK( pre_mem_read, tid, "semctl(IPC_SET, arg->buf)", buf,
2500 sizeof(struct semid64_ds) );
2501 break;
2502 }
2503 case GETALL|IPC_64:
2504 {
2505 Addr array = deref_Addr( tid, (Addr)&arg->array, "semctl(IPC_GETALL, arg)" );
2506 UInt nsems = get_sem_count( arg2 );
2507 SYSCALL_TRACK( pre_mem_write, tid, "semctl(IPC_GETALL, arg->array)", array,
2508 sizeof(short) * nsems );
2509 break;
2510 }
2511 case SETALL|IPC_64:
2512 {
2513 Addr array = deref_Addr( tid, (Addr)&arg->array, "semctl(IPC_SETALL, arg)" );
2514 UInt nsems = get_sem_count( arg2 );
2515 SYSCALL_TRACK( pre_mem_read, tid, "semctl(IPC_SETALL, arg->array)", array,
2516 sizeof(short) * nsems );
2517 break;
2518 }
2519 case SETVAL|IPC_64:
2520 {
2521 SYSCALL_TRACK( pre_mem_read, tid, "semctl(IPC_SETVAL, arg->array)",
2522 (Addr)&arg->val, sizeof(arg->val) );
2523 break;
2524 }
2525# endif
2526 default:
2527 break;
2528 }
2529 break;
2530 }
thughes03766282004-06-13 14:23:00 +00002531 case 4: /* IPCOP_semtimedop */
2532 SYSCALL_TRACK( pre_mem_read, tid, "semtimedop(sops)", arg5,
2533 arg3 * sizeof(struct sembuf) );
2534 if (arg6 != (UInt)NULL)
thughes60797102004-08-13 22:21:51 +00002535 SYSCALL_TRACK( pre_mem_read, tid, "semtimedop(timeout)", arg6,
thughes03766282004-06-13 14:23:00 +00002536 sizeof(struct timespec) );
thughes024f25d2004-07-29 22:40:07 +00002537 tst->sys_flags |= MayBlock;
thughes03766282004-06-13 14:23:00 +00002538 break;
jsgf855d93d2003-10-13 22:26:55 +00002539 case 11: /* IPCOP_msgsnd */
2540 {
2541 struct msgbuf *msgp = (struct msgbuf *)arg5;
2542 Int msgsz = arg3;
2543
2544 SYSCALL_TRACK( pre_mem_read, tid, "msgsnd(msgp->mtype)",
nethercotea8c1e922004-10-26 10:57:24 +00002545 (Addr)&msgp->mtype, sizeof(msgp->mtype) );
jsgf855d93d2003-10-13 22:26:55 +00002546 SYSCALL_TRACK( pre_mem_read, tid, "msgsnd(msgp->mtext)",
nethercotea8c1e922004-10-26 10:57:24 +00002547 (Addr)msgp->mtext, msgsz );
thughes024f25d2004-07-29 22:40:07 +00002548
2549 if ((arg4 & VKI_IPC_NOWAIT) == 0)
2550 tst->sys_flags |= MayBlock;
jsgf855d93d2003-10-13 22:26:55 +00002551 break;
2552 }
2553 case 12: /* IPCOP_msgrcv */
2554 {
2555 struct msgbuf *msgp;
2556 Int msgsz = arg3;
2557
2558 msgp = (struct msgbuf *)deref_Addr( tid,
2559 (Addr) (&((struct ipc_kludge *)arg5)->msgp),
2560 "msgrcv(msgp)" );
2561
2562 SYSCALL_TRACK( pre_mem_write, tid, "msgrcv(msgp->mtype)",
nethercotea8c1e922004-10-26 10:57:24 +00002563 (Addr)&msgp->mtype, sizeof(msgp->mtype) );
jsgf855d93d2003-10-13 22:26:55 +00002564 SYSCALL_TRACK( pre_mem_write, tid, "msgrcv(msgp->mtext)",
nethercotea8c1e922004-10-26 10:57:24 +00002565 (Addr)msgp->mtext, msgsz );
thughes024f25d2004-07-29 22:40:07 +00002566
2567 if ((arg4 & VKI_IPC_NOWAIT) == 0)
2568 tst->sys_flags |= MayBlock;
jsgf855d93d2003-10-13 22:26:55 +00002569 break;
2570 }
2571 case 13: /* IPCOP_msgget */
2572 break;
2573 case 14: /* IPCOP_msgctl */
2574 {
2575 switch (arg3 /* cmd */) {
thughes60797102004-08-13 22:21:51 +00002576 case IPC_INFO:
2577 case MSG_INFO:
2578 SYSCALL_TRACK( pre_mem_write, tid, "msgctl(IPC_INFO, buf)", arg5,
2579 sizeof(struct msginfo) );
2580 break;
jsgf855d93d2003-10-13 22:26:55 +00002581 case IPC_STAT:
thughes60797102004-08-13 22:21:51 +00002582 case MSG_STAT:
2583 SYSCALL_TRACK( pre_mem_write, tid, "msgctl(IPC_STAT, buf)", arg5,
jsgf855d93d2003-10-13 22:26:55 +00002584 sizeof(struct msqid_ds) );
2585 break;
2586 case IPC_SET:
thughes60797102004-08-13 22:21:51 +00002587 SYSCALL_TRACK( pre_mem_read, tid, "msgctl(IPC_SET, buf)", arg5,
jsgf855d93d2003-10-13 22:26:55 +00002588 sizeof(struct msqid_ds) );
2589 break;
2590# if defined(IPC_64)
thughes60797102004-08-13 22:21:51 +00002591 case IPC_INFO|IPC_64:
2592 case MSG_INFO|IPC_64:
2593 SYSCALL_TRACK( pre_mem_write, tid, "msgctl(IPC_INFO, buf)", arg5,
2594 sizeof(struct msginfo) );
2595 break;
jsgf855d93d2003-10-13 22:26:55 +00002596 case IPC_STAT|IPC_64:
thughes60797102004-08-13 22:21:51 +00002597 case MSG_STAT|IPC_64:
2598 SYSCALL_TRACK( pre_mem_write, tid, "msgctl(IPC_STAT, buf)", arg5,
jsgf855d93d2003-10-13 22:26:55 +00002599 sizeof(struct msqid64_ds) );
2600 break;
jsgf855d93d2003-10-13 22:26:55 +00002601 case IPC_SET|IPC_64:
thughes60797102004-08-13 22:21:51 +00002602 SYSCALL_TRACK( pre_mem_read, tid, "msgctl(IPC_SET, buf)", arg5,
jsgf855d93d2003-10-13 22:26:55 +00002603 sizeof(struct msqid64_ds) );
2604 break;
2605# endif
2606 default:
2607 break;
2608 }
2609 break;
2610 }
2611 case 21: /* IPCOP_shmat */
2612 {
fitzhardinge98abfc72003-12-16 02:05:15 +00002613 UInt shmid = arg2;
2614 UInt segmentSize = get_shm_size ( shmid );
2615
2616 /* If they didn't ask for a particular address, then place it
2617 like an mmap. */
2618 if (arg5 == 0)
2619 arg5 = VG_(find_map_space)(0, segmentSize, True);
2620 else if (!valid_client_addr(arg5, segmentSize, tid, "shmat"))
nethercote35122912004-10-18 17:00:30 +00002621 set_result( -VKI_EINVAL );
jsgf855d93d2003-10-13 22:26:55 +00002622 break;
2623 }
2624 case 22: /* IPCOP_shmdt */
fitzhardinged25e8a22004-02-25 00:07:10 +00002625 if (!valid_client_addr(arg5, 1, tid, "shmdt"))
nethercote35122912004-10-18 17:00:30 +00002626 set_result( -VKI_EINVAL );
jsgf855d93d2003-10-13 22:26:55 +00002627 break;
2628 case 23: /* IPCOP_shmget */
2629 break;
2630 case 24: /* IPCOP_shmctl */
jsgf855d93d2003-10-13 22:26:55 +00002631 {
thughes60797102004-08-13 22:21:51 +00002632 switch (arg3 /* cmd */) {
2633 case IPC_INFO:
2634 SYSCALL_TRACK( pre_mem_write, tid, "shmctl(IPC_INFO, buf)", arg5,
2635 sizeof(struct shminfo) );
2636 break;
2637 case SHM_INFO:
2638 SYSCALL_TRACK( pre_mem_write, tid, "shmctl(SHM_INFO, buf)", arg5,
2639 sizeof(struct shm_info) );
2640 break;
2641 case IPC_STAT:
2642 case SHM_STAT:
2643 SYSCALL_TRACK( pre_mem_write, tid, "shmctl(IPC_STAT, buf)", arg5,
2644 sizeof(struct shmid_ds) );
2645 break;
2646 case IPC_SET:
2647 SYSCALL_TRACK( pre_mem_read, tid, "shmctl(IPC_SET, buf)", arg5,
2648 sizeof(struct shmid_ds) );
2649 break;
jsgf855d93d2003-10-13 22:26:55 +00002650# if defined(IPC_64)
thughes60797102004-08-13 22:21:51 +00002651 case IPC_INFO|IPC_64:
2652 SYSCALL_TRACK( pre_mem_write, tid, "shmctl(IPC_INFO, buf)", arg5,
2653 sizeof(struct shminfo64) );
2654 break;
2655 case SHM_INFO|IPC_64:
2656 SYSCALL_TRACK( pre_mem_write, tid, "shmctl(SHM_INFO, buf)", arg5,
2657 sizeof(struct shm_info) );
2658 break;
2659 case IPC_STAT|IPC_64:
2660 case SHM_STAT|IPC_64:
2661 SYSCALL_TRACK( pre_mem_write, tid, "shmctl(IPC_STAT, buf)", arg5,
2662 sizeof(struct shmid64_ds) );
2663 break;
2664 case IPC_SET|IPC_64:
2665 SYSCALL_TRACK( pre_mem_read, tid, "shmctl(IPC_SET, buf)", arg5,
2666 sizeof(struct shmid_ds) );
2667 break;
jsgf855d93d2003-10-13 22:26:55 +00002668# endif
thughes60797102004-08-13 22:21:51 +00002669 default:
2670 break;
jsgf855d93d2003-10-13 22:26:55 +00002671 }
thughes60797102004-08-13 22:21:51 +00002672 break;
jsgf855d93d2003-10-13 22:26:55 +00002673 }
jsgf855d93d2003-10-13 22:26:55 +00002674 default:
2675 VG_(message)(Vg_DebugMsg,
2676 "FATAL: unhandled syscall(ipc) %d",
2677 arg1 );
2678 VG_(core_panic)("... bye!\n");
2679 break; /*NOTREACHED*/
2680 }
2681}
2682
2683POST(ipc)
2684{
2685 switch (arg1 /* call */) {
2686 case 1: /* IPCOP_semop */
jsgf855d93d2003-10-13 22:26:55 +00002687 case 2: /* IPCOP_semget */
thughes60797102004-08-13 22:21:51 +00002688 break;
jsgf855d93d2003-10-13 22:26:55 +00002689 case 3: /* IPCOP_semctl */
thughes60797102004-08-13 22:21:51 +00002690 {
2691 union semun *arg = (union semun *)arg5;
2692 switch (arg4 /* cmd */) {
2693 case IPC_INFO:
2694 case SEM_INFO:
2695 {
2696 Addr buf = deref_Addr( tid, (Addr)&arg->__buf, "semctl(arg)" );
2697 VG_TRACK( post_mem_write, buf, sizeof(struct seminfo) );
2698 break;
2699 }
2700 case IPC_STAT:
2701 case SEM_STAT:
2702 {
2703 Addr buf = deref_Addr( tid, (Addr)&arg->buf, "semctl(arg)" );
2704 VG_TRACK( post_mem_write, buf, sizeof(struct semid_ds) );
2705 break;
2706 }
2707 case GETALL:
2708 {
2709 Addr array = deref_Addr( tid, (Addr)&arg->array, "semctl(arg)" );
2710 UInt nsems = get_sem_count( arg2 );
2711 VG_TRACK( post_mem_write, array, sizeof(short) * nsems );
2712 break;
2713 }
2714# if defined(IPC_64)
2715 case IPC_INFO|IPC_64:
2716 case SEM_INFO|IPC_64:
2717 {
2718 Addr buf = deref_Addr( tid, (Addr)&arg->__buf, "semctl(arg)" );
2719 VG_TRACK( post_mem_write, buf, sizeof(struct seminfo) );
2720 break;
2721 }
2722 case IPC_STAT|IPC_64:
2723 case SEM_STAT|IPC_64:
2724 {
2725 Addr buf = deref_Addr( tid, (Addr)&arg->buf, "semctl(arg)" );
2726 VG_TRACK( post_mem_write, buf, sizeof(struct semid64_ds) );
2727 break;
2728 }
2729 case GETALL|IPC_64:
2730 {
2731 Addr array = deref_Addr( tid, (Addr)&arg->array, "semctl(arg)" );
2732 UInt nsems = get_sem_count( arg2 );
2733 VG_TRACK( post_mem_write, array, sizeof(short) * nsems );
2734 break;
2735 }
2736# endif
2737 default:
2738 break;
2739 }
2740 break;
2741 }
thughes03766282004-06-13 14:23:00 +00002742 case 4: /* IPCOP_semtimedop */
jsgf855d93d2003-10-13 22:26:55 +00002743 break;
2744 case 11: /* IPCOP_msgsnd */
2745 break;
2746 case 12: /* IPCOP_msgrcv */
2747 {
2748 struct msgbuf *msgp;
2749
2750 msgp = (struct msgbuf *)deref_Addr( tid,
2751 (Addr) (&((struct ipc_kludge *)arg5)->msgp),
2752 "msgrcv(msgp)" );
2753 if ( res > 0 ) {
nethercotea8c1e922004-10-26 10:57:24 +00002754 VG_TRACK( post_mem_write, (Addr)&msgp->mtype,
jsgf855d93d2003-10-13 22:26:55 +00002755 sizeof(msgp->mtype) );
nethercotea8c1e922004-10-26 10:57:24 +00002756 VG_TRACK( post_mem_write, (Addr)msgp->mtext, res );
jsgf855d93d2003-10-13 22:26:55 +00002757 }
2758 break;
2759 }
2760 case 13: /* IPCOP_msgget */
2761 break;
2762 case 14: /* IPCOP_msgctl */
2763 {
2764 switch (arg3 /* cmd */) {
thughes60797102004-08-13 22:21:51 +00002765 case IPC_INFO:
2766 case MSG_INFO:
2767 VG_TRACK( post_mem_write, arg5, sizeof(struct msginfo) );
2768 break;
jsgf855d93d2003-10-13 22:26:55 +00002769 case IPC_STAT:
thughes60797102004-08-13 22:21:51 +00002770 case MSG_STAT:
2771 VG_TRACK( post_mem_write, arg5, sizeof(struct msqid_ds) );
jsgf855d93d2003-10-13 22:26:55 +00002772 break;
2773 case IPC_SET:
2774 break;
2775# if defined(IPC_64)
thughes60797102004-08-13 22:21:51 +00002776 case IPC_INFO|IPC_64:
2777 case MSG_INFO|IPC_64:
2778 VG_TRACK( post_mem_write, arg5, sizeof(struct msginfo) );
jsgf855d93d2003-10-13 22:26:55 +00002779 break;
thughes60797102004-08-13 22:21:51 +00002780 case IPC_STAT|IPC_64:
2781 case MSG_STAT|IPC_64:
2782 VG_TRACK( post_mem_write, arg5, sizeof(struct msqid64_ds) );
2783 break;
jsgf855d93d2003-10-13 22:26:55 +00002784 case IPC_SET|IPC_64:
2785 break;
2786# endif
2787 default:
2788 break;
2789 }
2790 break;
2791 }
2792 case 21: /* IPCOP_shmat */
2793 {
2794 Int shmid = arg2;
fitzhardinge98abfc72003-12-16 02:05:15 +00002795 Int shmflag = arg3;
jsgf855d93d2003-10-13 22:26:55 +00002796 Addr addr;
2797
jsgf855d93d2003-10-13 22:26:55 +00002798 /* force readability. before the syscall it is
2799 * indeed uninitialized, as can be seen in
2800 * glibc/sysdeps/unix/sysv/linux/shmat.c */
2801 VG_TRACK( post_mem_write, arg4, sizeof( ULong ) );
2802
2803 addr = deref_Addr ( tid, arg4, "shmat(addr)" );
2804 if ( addr > 0 ) {
2805 UInt segmentSize = get_shm_size ( shmid );
2806 if ( segmentSize > 0 ) {
nethercote27ea8bc2004-07-10 17:21:14 +00002807 UInt prot = VKI_PROT_READ|VKI_PROT_WRITE;
jsgf855d93d2003-10-13 22:26:55 +00002808 /* we don't distinguish whether it's read-only or
2809 * read-write -- it doesn't matter really. */
nethercote071c84a2004-07-10 17:30:07 +00002810 VG_TRACK( new_mem_mmap, addr, segmentSize, True, True, False );
fitzhardinge98abfc72003-12-16 02:05:15 +00002811
fitzhardinge98abfc72003-12-16 02:05:15 +00002812 if (!(shmflag & 010000)) /* = SHM_RDONLY */
2813 prot &= ~VKI_PROT_WRITE;
nethercote27ea8bc2004-07-10 17:21:14 +00002814 VG_(map_segment)(addr, segmentSize, prot, SF_SHARED|SF_SHM);
jsgf855d93d2003-10-13 22:26:55 +00002815 }
2816 }
2817 break;
2818 }
2819 case 22: /* IPCOP_shmdt */
fitzhardinge98abfc72003-12-16 02:05:15 +00002820 {
fitzhardinged25e8a22004-02-25 00:07:10 +00002821 Segment *s = VG_(find_segment)(arg5);
fitzhardinge98abfc72003-12-16 02:05:15 +00002822
fitzhardinged25e8a22004-02-25 00:07:10 +00002823 if (s != NULL && (s->flags & SF_SHM) && VG_(seg_contains)(s, arg5, 1)) {
fitzhardinge98abfc72003-12-16 02:05:15 +00002824 VG_TRACK( die_mem_munmap, s->addr, s->len );
2825 VG_(unmap_range)(s->addr, s->len);
2826 }
jsgf855d93d2003-10-13 22:26:55 +00002827 break;
fitzhardinge98abfc72003-12-16 02:05:15 +00002828 }
jsgf855d93d2003-10-13 22:26:55 +00002829 case 23: /* IPCOP_shmget */
2830 break;
2831 case 24: /* IPCOP_shmctl */
jsgf855d93d2003-10-13 22:26:55 +00002832 {
thughes60797102004-08-13 22:21:51 +00002833 switch (arg3 /* cmd */) {
2834 case IPC_INFO:
2835 VG_TRACK( post_mem_write, arg5, sizeof(struct shminfo) );
2836 break;
2837 case SHM_INFO:
2838 VG_TRACK( post_mem_write, arg5, sizeof(struct shm_info) );
2839 break;
2840 case IPC_STAT:
2841 case SHM_STAT:
2842 VG_TRACK( post_mem_write, arg5, sizeof(struct shmid_ds) );
2843 break;
jsgf855d93d2003-10-13 22:26:55 +00002844# if defined(IPC_64)
thughes60797102004-08-13 22:21:51 +00002845 case IPC_INFO|IPC_64:
2846 VG_TRACK( post_mem_write, arg5, sizeof(struct shminfo64) );
2847 break;
2848 case SHM_INFO|IPC_64:
2849 VG_TRACK( post_mem_write, arg5, sizeof(struct shm_info) );
2850 break;
2851 case IPC_STAT|IPC_64:
2852 case SHM_STAT|IPC_64:
2853 VG_TRACK( post_mem_write, arg5, sizeof(struct shmid64_ds) );
2854 break;
jsgf855d93d2003-10-13 22:26:55 +00002855# endif
thughes60797102004-08-13 22:21:51 +00002856 default:
2857 break;
jsgf855d93d2003-10-13 22:26:55 +00002858 }
thughes60797102004-08-13 22:21:51 +00002859 break;
jsgf855d93d2003-10-13 22:26:55 +00002860 }
jsgf855d93d2003-10-13 22:26:55 +00002861 default:
2862 VG_(message)(Vg_DebugMsg,
2863 "FATAL: unhandled syscall(ipc) %d",
2864 arg1 );
2865 VG_(core_panic)("... bye!\n");
2866 break; /*NOTREACHED*/
2867 }
2868}
2869
2870PRE(ioctl)
2871{
2872 /* int ioctl(int d, int request, ...)
2873 [The "third" argument is traditionally char *argp,
2874 and will be so named for this discussion.]
2875 */
2876 /*
2877 VG_(message)(
2878 Vg_DebugMsg,
2879 "is an IOCTL, request = 0x%x, d = %d, argp = 0x%x",
2880 arg2,arg1,arg3);
2881 */
2882 MAYBE_PRINTF("ioctl ( %d, 0x%x, %p )\n",arg1,arg2,arg3);
2883 switch (arg2 /* request */) {
2884 case TCSETS:
2885 case TCSETSW:
2886 case TCSETSF:
2887 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TCSET{S,SW,SF})", arg3,
2888 VKI_SIZEOF_STRUCT_TERMIOS );
2889 break;
2890 case TCGETS:
2891 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TCGETS)", arg3,
2892 VKI_SIZEOF_STRUCT_TERMIOS );
2893 break;
2894 case TCSETA:
2895 case TCSETAW:
2896 case TCSETAF:
2897 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TCSET{A,AW,AF})", arg3,
2898 VKI_SIZEOF_STRUCT_TERMIO );
2899 break;
2900 case TCGETA:
2901 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TCGETA)", arg3,
2902 VKI_SIZEOF_STRUCT_TERMIO );
2903 break;
2904 case TCSBRK:
2905 case TCXONC:
2906 case TCSBRKP:
2907 case TCFLSH:
2908 /* These just take an int by value */
2909 break;
2910 case TIOCGWINSZ:
2911 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TIOCGWINSZ)", arg3,
2912 sizeof(struct winsize) );
2913 break;
2914 case TIOCSWINSZ:
2915 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TIOCSWINSZ)", arg3,
2916 sizeof(struct winsize) );
2917 break;
thughesfc5cd002004-09-11 14:37:04 +00002918 case TIOCMBIS:
2919 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TIOCMBIS)", arg3,
2920 sizeof(unsigned int) );
2921 break;
2922 case TIOCMBIC:
2923 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TIOCMBIC)", arg3,
2924 sizeof(unsigned int) );
2925 break;
2926 case TIOCMSET:
2927 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TIOCMSET)", arg3,
2928 sizeof(unsigned int) );
2929 break;
jsgf855d93d2003-10-13 22:26:55 +00002930 case TIOCLINUX:
2931 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TIOCLINUX)", arg3,
2932 sizeof(char *) );
2933 if (*(char *)arg3 == 11) {
2934 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TIOCLINUX, 11)",
2935 arg3, 2 * sizeof(char *) );
2936 }
2937 break;
2938 case TIOCGPGRP:
2939 /* Get process group ID for foreground processing group. */
2940 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TIOCGPGRP)", arg3,
2941 sizeof(pid_t) );
2942 break;
2943 case TIOCSPGRP:
2944 /* Set a process group ID? */
2945 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TIOCGPGRP)", arg3,
2946 sizeof(pid_t) );
2947 break;
2948 case TIOCGPTN: /* Get Pty Number (of pty-mux device) */
2949 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TIOCGPTN)",
2950 arg3, sizeof(int) );
2951 break;
2952 case TIOCSCTTY:
2953 /* Just takes an int value. */
2954 break;
2955 case TIOCSPTLCK: /* Lock/unlock Pty */
2956 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TIOCSPTLCK)",
2957 arg3, sizeof(int) );
2958 break;
2959 case FIONBIO:
2960 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(FIONBIO)",
2961 arg3, sizeof(int) );
2962 break;
2963 case FIOASYNC:
2964 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(FIOASYNC)",
2965 arg3, sizeof(int) );
2966 break;
2967 case FIONREAD: /* identical to SIOCINQ */
2968 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(FIONREAD)",
2969 arg3, sizeof(int) );
2970 break;
2971
2972 /* If you get compilation problems here, change the #if
2973 1 to #if 0 and get rid of <scsi/sg.h> in
2974 vg_unsafe.h. */
2975# if 1
2976 case SG_SET_COMMAND_Q:
2977 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SG_SET_COMMAND_Q)",
2978 arg3, sizeof(int) );
2979 break;
2980# if defined(SG_IO)
2981 case SG_IO:
2982 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SG_IO)", arg3,
2983 sizeof(struct sg_io_hdr) );
2984 break;
2985# endif /* SG_IO */
2986 case SG_GET_SCSI_ID:
2987 /* Note: sometimes sg_scsi_id is called sg_scsi_id_t */
2988 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SG_GET_SCSI_ID)", arg3,
2989 sizeof(struct sg_scsi_id) );
2990 break;
2991 case SG_SET_RESERVED_SIZE:
2992 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SG_SET_RESERVED_SIZE)",
2993 arg3, sizeof(int) );
2994 break;
2995 case SG_SET_TIMEOUT:
2996 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SG_SET_TIMEOUT)", arg3,
2997 sizeof(int) );
2998 break;
2999 case SG_GET_RESERVED_SIZE:
3000 SYSCALL_TRACK( pre_mem_write, tid,
3001 "ioctl(SG_GET_RESERVED_SIZE)", arg3,
3002 sizeof(int) );
3003 break;
3004 case SG_GET_TIMEOUT:
3005 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SG_GET_TIMEOUT)", arg3,
3006 sizeof(int) );
3007 break;
3008 case SG_GET_VERSION_NUM:
3009 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SG_GET_VERSION_NUM)",
3010 arg3, sizeof(int) );
3011 break;
thughes5b788fb2004-09-11 15:07:14 +00003012 case SG_EMULATED_HOST: /* 0x2203 */
3013 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SG_EMULATED_HOST)",
3014 arg3, sizeof(int) );
3015 break;
3016 case SG_GET_SG_TABLESIZE: /* 0x227f */
3017 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SG_GET_SG_TABLESIZE)",
3018 arg3, sizeof(int) );
3019 break;
jsgf855d93d2003-10-13 22:26:55 +00003020# endif
3021
muellera4b153a2003-11-19 22:07:14 +00003022 case VKI_IIOCGETCPS:
jsgf855d93d2003-10-13 22:26:55 +00003023 /* In early 2.4 kernels, ISDN_MAX_CHANNELS was only defined
3024 * when KERNEL was. I never saw a larger value than 64 though */
3025# ifndef ISDN_MAX_CHANNELS
3026# define ISDN_MAX_CHANNELS 64
3027# endif
3028 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(IIOCGETCPS)", arg3,
3029 ISDN_MAX_CHANNELS
3030 * 2 * sizeof(unsigned long) );
3031 break;
muellera4b153a2003-11-19 22:07:14 +00003032 case VKI_IIOCNETGPN:
jsgf855d93d2003-10-13 22:26:55 +00003033 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(IIOCNETGPN)",
nethercotea8c1e922004-10-26 10:57:24 +00003034 (Addr)&((isdn_net_ioctl_phone *)arg3)->name,
jsgf855d93d2003-10-13 22:26:55 +00003035 sizeof(((isdn_net_ioctl_phone *)arg3)->name) );
3036 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(IIOCNETGPN)", arg3,
3037 sizeof(isdn_net_ioctl_phone) );
3038 break;
3039
3040 /* These all use struct ifreq AFAIK */
thughesbe811712004-06-17 23:04:58 +00003041 case SIOCGIFINDEX: /* get iface index */
3042 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCGIFINDEX)",
nethercotea8c1e922004-10-26 10:57:24 +00003043 (Addr)((struct ifreq *)arg3)->ifr_name );
thughesbe811712004-06-17 23:04:58 +00003044 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFINDEX)", arg3,
jsgf855d93d2003-10-13 22:26:55 +00003045 sizeof(struct ifreq));
3046 break;
thughesbe811712004-06-17 23:04:58 +00003047 case SIOCGIFFLAGS: /* get flags */
3048 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCGIFFLAGS)",
nethercotea8c1e922004-10-26 10:57:24 +00003049 (Addr)((struct ifreq *)arg3)->ifr_name );
thughesbe811712004-06-17 23:04:58 +00003050 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFFLAGS)", arg3,
3051 sizeof(struct ifreq));
3052 break;
3053 case SIOCGIFHWADDR: /* Get hardware address */
3054 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCGIFHWADDR)",
nethercotea8c1e922004-10-26 10:57:24 +00003055 (Addr)((struct ifreq *)arg3)->ifr_name );
thughesbe811712004-06-17 23:04:58 +00003056 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFHWADDR)", arg3,
3057 sizeof(struct ifreq));
3058 break;
3059 case SIOCGIFMTU: /* get MTU size */
3060 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCGIFMTU)",
nethercotea8c1e922004-10-26 10:57:24 +00003061 (Addr)((struct ifreq *)arg3)->ifr_name );
thughesbe811712004-06-17 23:04:58 +00003062 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFMTU)", arg3,
3063 sizeof(struct ifreq));
3064 break;
3065 case SIOCGIFADDR: /* get PA address */
3066 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCGIFADDR)",
nethercotea8c1e922004-10-26 10:57:24 +00003067 (Addr)((struct ifreq *)arg3)->ifr_name );
thughesbe811712004-06-17 23:04:58 +00003068 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFADDR)", arg3,
3069 sizeof(struct ifreq));
3070 break;
3071 case SIOCGIFNETMASK: /* get network PA mask */
3072 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCGIFNETMASK)",
nethercotea8c1e922004-10-26 10:57:24 +00003073 (Addr)((struct ifreq *)arg3)->ifr_name );
thughesbe811712004-06-17 23:04:58 +00003074 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFNETMASK)", arg3,
3075 sizeof(struct ifreq));
3076 break;
3077 case SIOCGIFMETRIC: /* get metric */
3078 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCGIFMETRIC)",
nethercotea8c1e922004-10-26 10:57:24 +00003079 (Addr)((struct ifreq *)arg3)->ifr_name );
thughesbe811712004-06-17 23:04:58 +00003080 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFMETRIC)", arg3,
3081 sizeof(struct ifreq));
3082 break;
3083 case SIOCGIFMAP: /* Get device parameters */
3084 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCGIFMAP)",
nethercotea8c1e922004-10-26 10:57:24 +00003085 (Addr)((struct ifreq *)arg3)->ifr_name );
thughesbe811712004-06-17 23:04:58 +00003086 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFMAP)", arg3,
3087 sizeof(struct ifreq));
3088 break;
3089 case SIOCGIFTXQLEN: /* Get the tx queue length */
3090 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCGIFTXQLEN)",
nethercotea8c1e922004-10-26 10:57:24 +00003091 (Addr)((struct ifreq *)arg3)->ifr_name );
thughesbe811712004-06-17 23:04:58 +00003092 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFTXQLEN)", arg3,
3093 sizeof(struct ifreq));
3094 break;
3095 case SIOCGIFDSTADDR: /* get remote PA address */
3096 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCGIFDSTADDR)",
nethercotea8c1e922004-10-26 10:57:24 +00003097 (Addr)((struct ifreq *)arg3)->ifr_name );
thughesbe811712004-06-17 23:04:58 +00003098 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFDSTADDR)", arg3,
3099 sizeof(struct ifreq));
3100 break;
3101 case SIOCGIFBRDADDR: /* get broadcast PA address */
3102 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCGIFBRDADDR)",
nethercotea8c1e922004-10-26 10:57:24 +00003103 (Addr)((struct ifreq *)arg3)->ifr_name );
thughesbe811712004-06-17 23:04:58 +00003104 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFBRDADDR)", arg3,
3105 sizeof(struct ifreq));
3106 break;
3107 case SIOCGIFNAME: /* get iface name */
3108 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCGIFNAME)",
nethercotea8c1e922004-10-26 10:57:24 +00003109 (Addr)((struct ifreq *)arg3)->ifr_ifindex,
thughesbe811712004-06-17 23:04:58 +00003110 sizeof(((struct ifreq *)arg3)->ifr_ifindex) );
3111 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFNAME)", arg3,
3112 sizeof(struct ifreq));
3113 break;
3114#ifdef HAVE_LINUX_MII_H
3115 case SIOCGMIIPHY: /* get hardware entry */
3116 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCGIFMIIPHY)",
nethercotea8c1e922004-10-26 10:57:24 +00003117 (Addr)((struct ifreq *)arg3)->ifr_name );
thughesbe811712004-06-17 23:04:58 +00003118 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFMIIPHY)", arg3,
3119 sizeof(struct ifreq));
3120 break;
3121 case SIOCGMIIREG: /* get hardware entry registers */
3122 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCGIFMIIREG)",
nethercotea8c1e922004-10-26 10:57:24 +00003123 (Addr)((struct ifreq *)arg3)->ifr_name );
thughesbe811712004-06-17 23:04:58 +00003124 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCGIFMIIREG)",
nethercotea8c1e922004-10-26 10:57:24 +00003125 (Addr)&((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->phy_id,
thughesbe811712004-06-17 23:04:58 +00003126 sizeof(((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->phy_id) );
3127 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCGIFMIIREG)",
nethercotea8c1e922004-10-26 10:57:24 +00003128 (Addr)&((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->reg_num,
thughesbe811712004-06-17 23:04:58 +00003129 sizeof(((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->reg_num) );
3130 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFMIIREG)", arg3,
3131 sizeof(struct ifreq));
3132 break;
3133#endif
jsgf855d93d2003-10-13 22:26:55 +00003134 case SIOCGIFCONF: /* get iface list */
3135 /* WAS:
3136 SYSCALL_TRACK( pre_mem_write,"ioctl(SIOCGIFCONF)", arg3,
3137 sizeof(struct ifconf));
3138 KERNEL_DO_SYSCALL(tid,res);
3139 if (!VG_(is_kerror)(res) && res == 0)
3140 VG_TRACK( post_mem_write,arg3, sizeof(struct ifconf));
3141 */
3142 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(SIOCGIFCONF)", arg3,
3143 sizeof(struct ifconf));
3144 if ( arg3 ) {
3145 // TODO len must be readable and writable
3146 // buf pointer only needs to be readable
3147 struct ifconf *ifc = (struct ifconf *) arg3;
3148 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SIOCGIFCONF).ifc_buf",
3149 (Addr)(ifc->ifc_buf), (UInt)(ifc->ifc_len) );
3150 }
3151 break;
3152 case SIOCGSTAMP:
3153 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SIOCGSTAMP)", arg3,
3154 sizeof(struct timeval));
3155 break;
3156 /* SIOCOUTQ is an ioctl that, when called on a socket, returns
3157 the number of bytes currently in that socket's send buffer.
3158 It writes this value as an int to the memory location
3159 indicated by the third argument of ioctl(2). */
3160 case SIOCOUTQ:
3161 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SIOCOUTQ)", arg3,
3162 sizeof(int));
3163 break;
3164 case SIOCGRARP: /* get RARP table entry */
3165 case SIOCGARP: /* get ARP table entry */
3166 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SIOCGARP)", arg3,
3167 sizeof(struct arpreq));
3168 break;
3169
3170 case SIOCSIFFLAGS: /* set flags */
thughesbe811712004-06-17 23:04:58 +00003171 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCSIFFLAGS)",
nethercotea8c1e922004-10-26 10:57:24 +00003172 (Addr)((struct ifreq *)arg3)->ifr_name );
thughesbe811712004-06-17 23:04:58 +00003173 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCSIFFLAGS)",
nethercotea8c1e922004-10-26 10:57:24 +00003174 (Addr)&((struct ifreq *)arg3)->ifr_flags,
thughesbe811712004-06-17 23:04:58 +00003175 sizeof(((struct ifreq *)arg3)->ifr_flags) );
3176 break;
jsgf855d93d2003-10-13 22:26:55 +00003177 case SIOCSIFMAP: /* Set device parameters */
thughesbe811712004-06-17 23:04:58 +00003178 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCSIFMAP)",
nethercotea8c1e922004-10-26 10:57:24 +00003179 (Addr)((struct ifreq *)arg3)->ifr_name );
thughesbe811712004-06-17 23:04:58 +00003180 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCSIFMAP)",
nethercotea8c1e922004-10-26 10:57:24 +00003181 (Addr)&((struct ifreq *)arg3)->ifr_map,
thughesbe811712004-06-17 23:04:58 +00003182 sizeof(((struct ifreq *)arg3)->ifr_map) );
3183 break;
jsgf855d93d2003-10-13 22:26:55 +00003184 case SIOCSIFTXQLEN: /* Set the tx queue length */
thughesbe811712004-06-17 23:04:58 +00003185 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCSIFTXQLEN)",
nethercotea8c1e922004-10-26 10:57:24 +00003186 (Addr)((struct ifreq *)arg3)->ifr_name );
thughesbe811712004-06-17 23:04:58 +00003187 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCSIFTXQLEN)",
nethercotea8c1e922004-10-26 10:57:24 +00003188 (Addr)&((struct ifreq *)arg3)->ifr_qlen,
thughesbe811712004-06-17 23:04:58 +00003189 sizeof(((struct ifreq *)arg3)->ifr_qlen) );
3190 break;
3191 case SIOCSIFADDR: /* set PA address */
jsgf855d93d2003-10-13 22:26:55 +00003192 case SIOCSIFDSTADDR: /* set remote PA address */
3193 case SIOCSIFBRDADDR: /* set broadcast PA address */
3194 case SIOCSIFNETMASK: /* set network PA mask */
thughesbe811712004-06-17 23:04:58 +00003195 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCSIF*ADDR)",
nethercotea8c1e922004-10-26 10:57:24 +00003196 (Addr)((struct ifreq *)arg3)->ifr_name );
thughesbe811712004-06-17 23:04:58 +00003197 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCSIF*ADDR)",
nethercotea8c1e922004-10-26 10:57:24 +00003198 (Addr)&((struct ifreq *)arg3)->ifr_addr,
thughesbe811712004-06-17 23:04:58 +00003199 sizeof(((struct ifreq *)arg3)->ifr_addr) );
jsgf855d93d2003-10-13 22:26:55 +00003200 break;
thughesbe811712004-06-17 23:04:58 +00003201 case SIOCSIFMETRIC: /* set metric */
3202 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCSIFMETRIC)",
nethercotea8c1e922004-10-26 10:57:24 +00003203 (Addr)((struct ifreq *)arg3)->ifr_name );
thughesbe811712004-06-17 23:04:58 +00003204 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCSIFMETRIC)",
nethercotea8c1e922004-10-26 10:57:24 +00003205 (Addr)&((struct ifreq *)arg3)->ifr_metric,
thughesbe811712004-06-17 23:04:58 +00003206 sizeof(((struct ifreq *)arg3)->ifr_metric) );
3207 break;
3208 case SIOCSIFMTU: /* set MTU size */
3209 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCSIFMTU)",
nethercotea8c1e922004-10-26 10:57:24 +00003210 (Addr)((struct ifreq *)arg3)->ifr_name );
thughesbe811712004-06-17 23:04:58 +00003211 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCSIFMTU)",
nethercotea8c1e922004-10-26 10:57:24 +00003212 (Addr)&((struct ifreq *)arg3)->ifr_mtu,
thughesbe811712004-06-17 23:04:58 +00003213 sizeof(((struct ifreq *)arg3)->ifr_mtu) );
3214 break;
3215 case SIOCSIFHWADDR: /* set hardware address */
3216 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCSIFHWADDR)",
nethercotea8c1e922004-10-26 10:57:24 +00003217 (Addr)((struct ifreq *)arg3)->ifr_name );
thughesbe811712004-06-17 23:04:58 +00003218 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCSIFHWADDR)",
nethercotea8c1e922004-10-26 10:57:24 +00003219 (Addr)&((struct ifreq *)arg3)->ifr_hwaddr,
thughesbe811712004-06-17 23:04:58 +00003220 sizeof(((struct ifreq *)arg3)->ifr_hwaddr) );
3221 break;
3222#ifdef HAVE_LINUX_MII_H
3223 case SIOCSMIIREG: /* set hardware entry registers */
3224 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCSMIIREG)",
nethercotea8c1e922004-10-26 10:57:24 +00003225 (Addr)((struct ifreq *)arg3)->ifr_name );
thughesbe811712004-06-17 23:04:58 +00003226 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCSMIIREG)",
nethercotea8c1e922004-10-26 10:57:24 +00003227 (Addr)&((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->phy_id,
thughesbe811712004-06-17 23:04:58 +00003228 sizeof(((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->phy_id) );
3229 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCSMIIREG)",
nethercotea8c1e922004-10-26 10:57:24 +00003230 (Addr)&((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->reg_num,
thughesbe811712004-06-17 23:04:58 +00003231 sizeof(((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->reg_num) );
3232 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCSMIIREG)",
nethercotea8c1e922004-10-26 10:57:24 +00003233 (Addr)&((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->val_in,
thughesbe811712004-06-17 23:04:58 +00003234 sizeof(((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->val_in) );
3235 break;
3236#endif
jsgf855d93d2003-10-13 22:26:55 +00003237 /* Routing table calls. */
3238 case SIOCADDRT: /* add routing table entry */
3239 case SIOCDELRT: /* delete routing table entry */
3240 SYSCALL_TRACK( pre_mem_read,tid,"ioctl(SIOCADDRT/DELRT)", arg3,
3241 sizeof(struct rtentry));
3242 break;
3243
3244 /* RARP cache control calls. */
3245 case SIOCDRARP: /* delete RARP table entry */
3246 case SIOCSRARP: /* set RARP table entry */
3247 /* ARP cache control calls. */
3248 case SIOCSARP: /* set ARP table entry */
3249 case SIOCDARP: /* delete ARP table entry */
3250 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(SIOCSIFFLAGS)", arg3,
3251 sizeof(struct ifreq));
3252 break;
3253
thughes1174fed2004-09-11 15:33:17 +00003254 case SIOCGPGRP:
3255 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGPGRP)", arg3,
3256 sizeof(int) );
3257 break;
jsgf855d93d2003-10-13 22:26:55 +00003258 case SIOCSPGRP:
3259 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCSPGRP)", arg3,
3260 sizeof(int) );
thughes1174fed2004-09-11 15:33:17 +00003261 tst->sys_flags &= ~MayBlock;
jsgf855d93d2003-10-13 22:26:55 +00003262 break;
3263
3264 /* linux/soundcard interface (OSS) */
3265 case SNDCTL_SEQ_GETOUTCOUNT:
3266 case SNDCTL_SEQ_GETINCOUNT:
3267 case SNDCTL_SEQ_PERCMODE:
3268 case SNDCTL_SEQ_TESTMIDI:
3269 case SNDCTL_SEQ_RESETSAMPLES:
3270 case SNDCTL_SEQ_NRSYNTHS:
3271 case SNDCTL_SEQ_NRMIDIS:
3272 case SNDCTL_SEQ_GETTIME:
3273 case SNDCTL_DSP_GETFMTS:
3274 case SNDCTL_DSP_GETTRIGGER:
3275 case SNDCTL_DSP_GETODELAY:
3276# if defined(SNDCTL_DSP_GETSPDIF)
3277 case SNDCTL_DSP_GETSPDIF:
3278# endif
3279 case SNDCTL_DSP_GETCAPS:
3280 case SOUND_PCM_READ_RATE:
3281 case SOUND_PCM_READ_CHANNELS:
3282 case SOUND_PCM_READ_BITS:
3283 case (SOUND_PCM_READ_BITS|0x40000000): /* what the fuck ? */
3284 case SOUND_PCM_READ_FILTER:
3285 SYSCALL_TRACK( pre_mem_write,tid,
3286 "ioctl(SNDCTL_XXX|SOUND_XXX (SIOR, int))",
3287 arg3,
3288 sizeof(int));
3289 break;
3290 case SNDCTL_SEQ_CTRLRATE:
3291 case SNDCTL_DSP_SPEED:
3292 case SNDCTL_DSP_STEREO:
3293 case SNDCTL_DSP_GETBLKSIZE:
3294 case SNDCTL_DSP_CHANNELS:
3295 case SOUND_PCM_WRITE_FILTER:
3296 case SNDCTL_DSP_SUBDIVIDE:
3297 case SNDCTL_DSP_SETFRAGMENT:
3298# if defined(SNDCTL_DSP_GETCHANNELMASK)
3299 case SNDCTL_DSP_GETCHANNELMASK:
3300# endif
3301# if defined(SNDCTL_DSP_BIND_CHANNEL)
3302 case SNDCTL_DSP_BIND_CHANNEL:
3303# endif
3304 case SNDCTL_TMR_TIMEBASE:
3305 case SNDCTL_TMR_TEMPO:
3306 case SNDCTL_TMR_SOURCE:
3307 case SNDCTL_MIDI_PRETIME:
3308 case SNDCTL_MIDI_MPUMODE:
3309 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(SNDCTL_XXX|SOUND_XXX "
3310 "(SIOWR, int))",
3311 arg3, sizeof(int));
3312 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SNDCTL_XXX|SOUND_XXX "
3313 "(SIOWR, int))",
3314 arg3, sizeof(int));
3315 break;
3316 case SNDCTL_DSP_GETOSPACE:
3317 case SNDCTL_DSP_GETISPACE:
3318 SYSCALL_TRACK( pre_mem_write,tid,
3319 "ioctl(SNDCTL_XXX|SOUND_XXX "
3320 "(SIOR, audio_buf_info))", arg3,
3321 sizeof(audio_buf_info));
3322 break;
3323 case SNDCTL_DSP_SETTRIGGER:
3324 SYSCALL_TRACK( pre_mem_read,tid,
3325 "ioctl(SNDCTL_XXX|SOUND_XXX (SIOW, int))",
3326 arg3, sizeof(int));
3327 break;
3328
3329 case SNDCTL_DSP_POST:
3330 case SNDCTL_DSP_RESET:
3331 case SNDCTL_DSP_SYNC:
3332 case SNDCTL_DSP_SETSYNCRO:
3333 case SNDCTL_DSP_SETDUPLEX:
3334 break;
3335
3336 /* Real Time Clock (/dev/rtc) ioctls */
3337# ifndef GLIBC_2_1
3338 case RTC_UIE_ON:
3339 case RTC_UIE_OFF:
3340 case RTC_AIE_ON:
3341 case RTC_AIE_OFF:
3342 case RTC_PIE_ON:
3343 case RTC_PIE_OFF:
3344 case RTC_IRQP_SET:
3345 break;
3346 case RTC_RD_TIME:
3347 case RTC_ALM_READ:
3348 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(RTC_RD_TIME/ALM_READ)",
3349 arg3, sizeof(struct rtc_time));
3350 break;
3351 case RTC_ALM_SET:
3352 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(RTC_ALM_SET)", arg3,
3353 sizeof(struct rtc_time));
3354 break;
3355 case RTC_IRQP_READ:
3356 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(RTC_IRQP_READ)", arg3,
3357 sizeof(unsigned long));
3358 break;
3359# endif /* GLIBC_2_1 */
3360
3361# ifdef BLKGETSIZE
3362 case BLKGETSIZE:
3363 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(BLKGETSIZE)", arg3,
3364 sizeof(unsigned long));
3365 break;
3366# endif /* BLKGETSIZE */
3367
thughesacbbc322004-06-19 12:12:01 +00003368 /* Hard disks */
3369 case HDIO_GET_IDENTITY: /* 0x030d */
3370 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(HDIO_GET_IDENTITY)", arg3,
3371 sizeof(struct hd_driveid) );
3372 break;
3373
jsgf855d93d2003-10-13 22:26:55 +00003374 /* CD ROM stuff (??) */
nethercote671398c2004-02-22 18:08:04 +00003375 case CDROM_GET_MCN:
3376 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(CDROM_GET_MCN)", arg3,
3377 sizeof(struct cdrom_mcn) );
3378 break;
3379 case CDROM_SEND_PACKET:
3380 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(CDROM_SEND_PACKET)", arg3,
3381 sizeof(struct cdrom_generic_command));
3382 break;
jsgf855d93d2003-10-13 22:26:55 +00003383 case CDROMSUBCHNL:
3384 SYSCALL_TRACK( pre_mem_read,tid,
3385 "ioctl(CDROMSUBCHNL (cdsc_format, char))",
3386 (int) &(((struct cdrom_subchnl *) arg3)->cdsc_format),
3387 sizeof(((struct cdrom_subchnl *) arg3)->cdsc_format));
3388 SYSCALL_TRACK( pre_mem_write,tid,
3389 "ioctl(CDROMSUBCHNL)", arg3,
3390 sizeof(struct cdrom_subchnl));
3391 break;
nethercote671398c2004-02-22 18:08:04 +00003392 case CDROMREADMODE2:
3393 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(CDROMREADMODE2)", arg3,
3394 CD_FRAMESIZE_RAW0 );
3395 break;
jsgf855d93d2003-10-13 22:26:55 +00003396 case CDROMREADTOCHDR:
3397 SYSCALL_TRACK( pre_mem_write,tid,
3398 "ioctl(CDROMREADTOCHDR)", arg3,
3399 sizeof(struct cdrom_tochdr));
3400 break;
3401 case CDROMREADTOCENTRY:
3402 SYSCALL_TRACK( pre_mem_read,tid,
3403 "ioctl(CDROMREADTOCENTRY (cdte_format, char))",
3404 (int) &(((struct cdrom_tocentry *) arg3)->cdte_format),
3405 sizeof(((struct cdrom_tocentry *) arg3)->cdte_format));
3406 SYSCALL_TRACK( pre_mem_read,tid,
3407 "ioctl(CDROMREADTOCENTRY (cdte_track, char))",
3408 (int) &(((struct cdrom_tocentry *) arg3)->cdte_track),
3409 sizeof(((struct cdrom_tocentry *) arg3)->cdte_track));
3410 SYSCALL_TRACK( pre_mem_write,tid,
3411 "ioctl(CDROMREADTOCENTRY)", arg3,
3412 sizeof(struct cdrom_tocentry));
3413 break;
thughes5b788fb2004-09-11 15:07:14 +00003414 case CDROMMULTISESSION: /* 0x5310 */
3415 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(CDROMMULTISESSION)", arg3,
3416 sizeof(struct cdrom_multisession));
3417 break;
3418 case CDROMVOLREAD: /* 0x5313 */
3419 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(CDROMVOLREAD)", arg3,
3420 sizeof(struct cdrom_volctrl));
3421 break;
3422 case CDROMREADAUDIO: /* 0x530e */
3423 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(CDROMREADAUDIO)", arg3,
3424 sizeof (struct cdrom_read_audio));
3425 if ( arg3 ) {
3426 /* ToDo: don't do any of the following if the structure is invalid */
3427 struct cdrom_read_audio *cra = (struct cdrom_read_audio *) arg3;
3428 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(CDROMREADAUDIO).buf",
3429 (Addr)(cra->buf),
3430 (UInt)(cra->nframes * CD_FRAMESIZE_RAW));
3431 }
3432 break;
jsgf855d93d2003-10-13 22:26:55 +00003433 case CDROMPLAYMSF:
3434 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(CDROMPLAYMSF)", arg3,
3435 sizeof(struct cdrom_msf));
3436 break;
3437 /* The following two are probably bogus (should check args
3438 for readability). JRS 20021117 */
3439 case CDROM_DRIVE_STATUS: /* 0x5326 */
3440 case CDROM_CLEAR_OPTIONS: /* 0x5321 */
3441 break;
thughes66d80092004-06-19 12:41:05 +00003442
3443 case FIGETBSZ:
3444 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(FIGETBSZ)", arg3,
3445 sizeof(unsigned long));
3446 break;
3447 case FIBMAP:
3448 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(FIBMAP)", arg3,
3449 sizeof(unsigned long));
3450 break;
3451
thughes1742d6f2004-04-22 07:28:43 +00003452#ifdef HAVE_LINUX_FB_H
thughes44e35582004-04-21 15:52:33 +00003453 case FBIOGET_VSCREENINFO: /* 0x4600 */
3454 SYSCALL_TRACK( pre_mem_write,tid,
3455 "ioctl(FBIOGET_VSCREENINFO)", arg3,
3456 sizeof(struct fb_var_screeninfo));
3457 break;
3458 case FBIOGET_FSCREENINFO: /* 0x4602 */
3459 SYSCALL_TRACK( pre_mem_write,tid,
3460 "ioctl(FBIOGET_FSCREENINFO)", arg3,
3461 sizeof(struct fb_fix_screeninfo));
3462 break;
thughes1742d6f2004-04-22 07:28:43 +00003463#endif
jsgf855d93d2003-10-13 22:26:55 +00003464
thughesd9895482004-08-16 19:46:55 +00003465 case PPCLAIM:
3466 case PPEXCL:
3467 case PPYIELD:
3468 case PPRELEASE:
3469 break;
3470 case PPSETMODE:
3471 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(PPSETMODE)", arg3,
3472 sizeof(int) );
3473 break;
thughesfb6f2002004-09-01 07:29:08 +00003474#ifdef PPGETMODE
thughesd9895482004-08-16 19:46:55 +00003475 case PPGETMODE:
3476 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(PPGETMODE)", arg3,
3477 sizeof(int) );
3478 break;
thughesfb6f2002004-09-01 07:29:08 +00003479#endif
thughesd9895482004-08-16 19:46:55 +00003480 case PPSETPHASE:
3481 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(PPSETPHASE)", arg3,
3482 sizeof(int) );
3483 break;
thughesfb6f2002004-09-01 07:29:08 +00003484#ifdef PPGETPHASE
thughesd9895482004-08-16 19:46:55 +00003485 case PPGETPHASE:
3486 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(PPGETPHASE)", arg3,
3487 sizeof(int) );
3488 break;
thughesfb6f2002004-09-01 07:29:08 +00003489#endif
3490#ifdef PPGETMODES
thughesd9895482004-08-16 19:46:55 +00003491 case PPGETMODES:
3492 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(PPGETMODES)", arg3,
3493 sizeof(unsigned int) );
3494 break;
thughesfb6f2002004-09-01 07:29:08 +00003495#endif
3496#ifdef PPSETFLAGS
thughesd9895482004-08-16 19:46:55 +00003497 case PPSETFLAGS:
3498 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(PPSETFLAGS)", arg3,
3499 sizeof(int) );
3500 break;
thughesfb6f2002004-09-01 07:29:08 +00003501#endif
3502#ifdef PPGETFLAGS
thughesd9895482004-08-16 19:46:55 +00003503 case PPGETFLAGS:
3504 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(PPGETFLAGS)", arg3,
3505 sizeof(int) );
3506 break;
thughesfb6f2002004-09-01 07:29:08 +00003507#endif
thughesd9895482004-08-16 19:46:55 +00003508 case PPRSTATUS:
3509 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(PPRSTATUS)", arg3,
3510 sizeof(unsigned char) );
3511 break;
3512 case PPRDATA:
3513 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(PPRDATA)", arg3,
3514 sizeof(unsigned char) );
3515 break;
3516 case PPRCONTROL:
3517 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(PPRCONTROL)", arg3,
3518 sizeof(unsigned char) );
3519 break;
3520 case PPWDATA:
3521 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(PPWDATA)", arg3,
3522 sizeof(unsigned char) );
3523 break;
3524 case PPWCONTROL:
3525 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(PPWCONTROL)", arg3,
3526 sizeof(unsigned char) );
3527 break;
3528 case PPFCONTROL:
3529 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(PPFCONTROL)", arg3,
3530 2 * sizeof(unsigned char) );
3531 break;
3532 case PPDATADIR:
3533 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(PPDATADIR)", arg3,
3534 sizeof(int) );
3535 break;
3536 case PPNEGOT:
3537 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(PPNEGOT)", arg3,
3538 sizeof(int) );
3539 break;
3540 case PPWCTLONIRQ:
3541 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(PPWCTLONIRQ)", arg3,
3542 sizeof(unsigned char) );
3543 break;
3544 case PPCLRIRQ:
3545 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(PPCLRIRQ)", arg3,
3546 sizeof(int) );
3547 break;
3548 case PPSETTIME:
3549 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(PPSETTIME)", arg3,
3550 sizeof(struct timeval) );
3551 break;
3552 case PPGETTIME:
3553 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(PPGETTIME)", arg3,
3554 sizeof(struct timeval) );
3555 break;
3556
jsgf855d93d2003-10-13 22:26:55 +00003557 /* We don't have any specific information on it, so
3558 try to do something reasonable based on direction and
3559 size bits. The encoding scheme is described in
3560 /usr/include/asm/ioctl.h.
3561
3562 According to Simon Hausmann, _IOC_READ means the kernel
3563 writes a value to the ioctl value passed from the user
3564 space and the other way around with _IOC_WRITE. */
3565 default: {
3566 UInt dir = _IOC_DIR(arg2);
3567 UInt size = _IOC_SIZE(arg2);
3568 if (VG_(strstr)(VG_(clo_weird_hacks), "lax-ioctls") != NULL) {
3569 /*
3570 * Be very lax about ioctl handling; the only
3571 * assumption is that the size is correct. Doesn't
3572 * require the full buffer to be initialized when
3573 * writing. Without this, using some device
3574 * drivers with a large number of strange ioctl
3575 * commands becomes very tiresome.
3576 */
3577 } else if (/* size == 0 || */ dir == _IOC_NONE) {
3578 static Int moans = 3;
3579 if (moans > 0) {
3580 moans--;
3581 VG_(message)(Vg_UserMsg,
3582 "Warning: noted but unhandled ioctl 0x%x"
3583 " with no size/direction hints",
3584 arg2);
3585 VG_(message)(Vg_UserMsg,
3586 " This could cause spurious value errors"
3587 " to appear.");
3588 VG_(message)(Vg_UserMsg,
3589 " See README_MISSING_SYSCALL_OR_IOCTL for "
3590 "guidance on writing a proper wrapper." );
3591 }
3592 } else {
3593 if ((dir & _IOC_WRITE) && size > 0)
3594 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(generic)",
3595 arg3, size);
3596 if ((dir & _IOC_READ) && size > 0)
3597 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(generic)",
3598 arg3, size);
3599 }
3600 break;
3601 }
3602 }
3603}
3604
3605POST(ioctl)
3606{
3607 /* int ioctl(int d, int request, ...)
3608 [The "third" argument is traditionally char *argp,
3609 and will be so named for this discussion.]
3610 */
3611 /*
3612 VG_(message)(
3613 Vg_DebugMsg,
3614 "is an IOCTL, request = 0x%x, d = %d, argp = 0x%x",
3615 arg2,arg1,arg3);
3616 */
3617 MAYBE_PRINTF("ioctl ( %d, 0x%x, %p )\n",arg1,arg2,arg3);
3618 switch (arg2 /* request */) {
3619 case TCSETS:
3620 case TCSETSW:
3621 case TCSETSF:
3622 break;
3623 case TCGETS:
thughes64326692004-09-11 15:14:59 +00003624 VG_TRACK( post_mem_write, arg3, VKI_SIZEOF_STRUCT_TERMIOS );
jsgf855d93d2003-10-13 22:26:55 +00003625 break;
3626 case TCSETA:
3627 case TCSETAW:
3628 case TCSETAF:
3629 break;
3630 case TCGETA:
thughes64326692004-09-11 15:14:59 +00003631 VG_TRACK( post_mem_write, arg3, VKI_SIZEOF_STRUCT_TERMIO );
jsgf855d93d2003-10-13 22:26:55 +00003632 break;
3633 case TCSBRK:
3634 case TCXONC:
3635 case TCSBRKP:
3636 case TCFLSH:
3637 break;
3638 case TIOCGWINSZ:
thughes64326692004-09-11 15:14:59 +00003639 VG_TRACK( post_mem_write, arg3, sizeof(struct winsize) );
jsgf855d93d2003-10-13 22:26:55 +00003640 break;
3641 case TIOCSWINSZ:
thughesfc5cd002004-09-11 14:37:04 +00003642 case TIOCMBIS:
3643 case TIOCMBIC:
3644 case TIOCMSET:
jsgf855d93d2003-10-13 22:26:55 +00003645 break;
3646 case TIOCLINUX:
thughes64326692004-09-11 15:14:59 +00003647 VG_TRACK( post_mem_write, arg3, sizeof(char *) );
jsgf855d93d2003-10-13 22:26:55 +00003648 break;
3649 case TIOCGPGRP:
3650 /* Get process group ID for foreground processing group. */
thughes64326692004-09-11 15:14:59 +00003651 VG_TRACK( post_mem_write, arg3, sizeof(pid_t) );
jsgf855d93d2003-10-13 22:26:55 +00003652 break;
3653 case TIOCSPGRP:
3654 /* Set a process group ID? */
thughes64326692004-09-11 15:14:59 +00003655 VG_TRACK( post_mem_write, arg3, sizeof(pid_t) );
jsgf855d93d2003-10-13 22:26:55 +00003656 break;
3657 case TIOCGPTN: /* Get Pty Number (of pty-mux device) */
thughes64326692004-09-11 15:14:59 +00003658 VG_TRACK( post_mem_write, arg3, sizeof(int));
jsgf855d93d2003-10-13 22:26:55 +00003659 break;
3660 case TIOCSCTTY:
3661 break;
3662 case TIOCSPTLCK: /* Lock/unlock Pty */
3663 break;
3664 case FIONBIO:
3665 break;
3666 case FIOASYNC:
3667 break;
3668 case FIONREAD: /* identical to SIOCINQ */
thughes64326692004-09-11 15:14:59 +00003669 VG_TRACK( post_mem_write, arg3, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00003670 break;
3671
3672 /* If you get compilation problems here, change the #if
3673 1 to #if 0 and get rid of <scsi/sg.h> in
3674 vg_unsafe.h. */
3675# if 1
3676 case SG_SET_COMMAND_Q:
3677 break;
3678# if defined(SG_IO)
3679 case SG_IO:
thughes64326692004-09-11 15:14:59 +00003680 VG_TRACK( post_mem_write,arg3, sizeof(struct sg_io_hdr));
jsgf855d93d2003-10-13 22:26:55 +00003681 break;
3682# endif /* SG_IO */
3683 case SG_GET_SCSI_ID:
thughes64326692004-09-11 15:14:59 +00003684 VG_TRACK( post_mem_write,arg3, sizeof(struct sg_scsi_id));
jsgf855d93d2003-10-13 22:26:55 +00003685 break;
3686 case SG_SET_RESERVED_SIZE:
3687 break;
3688 case SG_SET_TIMEOUT:
3689 break;
3690 case SG_GET_RESERVED_SIZE:
thughes64326692004-09-11 15:14:59 +00003691 VG_TRACK( post_mem_write,arg3, sizeof(int));
jsgf855d93d2003-10-13 22:26:55 +00003692 break;
3693 case SG_GET_TIMEOUT:
thughes64326692004-09-11 15:14:59 +00003694 VG_TRACK( post_mem_write,arg3, sizeof(int));
jsgf855d93d2003-10-13 22:26:55 +00003695 break;
3696 case SG_GET_VERSION_NUM:
3697 break;
thughes5b788fb2004-09-11 15:07:14 +00003698 case SG_EMULATED_HOST:
3699 VG_TRACK( post_mem_write,arg3, sizeof(int));
3700 break;
3701 case SG_GET_SG_TABLESIZE:
3702 VG_TRACK( post_mem_write,arg3, sizeof(int));
3703 break;
jsgf855d93d2003-10-13 22:26:55 +00003704# endif
3705
muellera4b153a2003-11-19 22:07:14 +00003706 case VKI_IIOCGETCPS:
jsgf855d93d2003-10-13 22:26:55 +00003707 /* In early 2.4 kernels, ISDN_MAX_CHANNELS was only defined
3708 * when KERNEL was. I never saw a larger value than 64 though */
3709# ifndef ISDN_MAX_CHANNELS
3710# define ISDN_MAX_CHANNELS 64
3711# endif
thughes64326692004-09-11 15:14:59 +00003712 VG_TRACK( post_mem_write, arg3,
3713 ISDN_MAX_CHANNELS * 2 * sizeof(unsigned long) );
jsgf855d93d2003-10-13 22:26:55 +00003714 break;
muellera4b153a2003-11-19 22:07:14 +00003715 case VKI_IIOCNETGPN:
thughes64326692004-09-11 15:14:59 +00003716 VG_TRACK( post_mem_write, arg3, sizeof(isdn_net_ioctl_phone) );
jsgf855d93d2003-10-13 22:26:55 +00003717 break;
3718
3719 /* These all use struct ifreq AFAIK */
thughesbe811712004-06-17 23:04:58 +00003720 case SIOCGIFINDEX: /* get iface index */
thughes64326692004-09-11 15:14:59 +00003721 VG_TRACK( post_mem_write,
nethercotea8c1e922004-10-26 10:57:24 +00003722 (Addr)&((struct ifreq *)arg3)->ifr_ifindex,
thughes64326692004-09-11 15:14:59 +00003723 sizeof(((struct ifreq *)arg3)->ifr_ifindex) );
thughesbe811712004-06-17 23:04:58 +00003724 break;
jsgf855d93d2003-10-13 22:26:55 +00003725 case SIOCGIFFLAGS: /* get flags */
thughes64326692004-09-11 15:14:59 +00003726 VG_TRACK( post_mem_write,
nethercotea8c1e922004-10-26 10:57:24 +00003727 (Addr)&((struct ifreq *)arg3)->ifr_flags,
thughes64326692004-09-11 15:14:59 +00003728 sizeof(((struct ifreq *)arg3)->ifr_flags) );
thughesbe811712004-06-17 23:04:58 +00003729 break;
jsgf855d93d2003-10-13 22:26:55 +00003730 case SIOCGIFHWADDR: /* Get hardware address */
thughes64326692004-09-11 15:14:59 +00003731 VG_TRACK( post_mem_write,
nethercotea8c1e922004-10-26 10:57:24 +00003732 (Addr)&((struct ifreq *)arg3)->ifr_hwaddr,
thughes64326692004-09-11 15:14:59 +00003733 sizeof(((struct ifreq *)arg3)->ifr_hwaddr) );
thughesbe811712004-06-17 23:04:58 +00003734 break;
jsgf855d93d2003-10-13 22:26:55 +00003735 case SIOCGIFMTU: /* get MTU size */
thughes64326692004-09-11 15:14:59 +00003736 VG_TRACK( post_mem_write,
nethercotea8c1e922004-10-26 10:57:24 +00003737 (Addr)&((struct ifreq *)arg3)->ifr_mtu,
thughes64326692004-09-11 15:14:59 +00003738 sizeof(((struct ifreq *)arg3)->ifr_mtu) );
thughesbe811712004-06-17 23:04:58 +00003739 break;
jsgf855d93d2003-10-13 22:26:55 +00003740 case SIOCGIFADDR: /* get PA address */
jsgf855d93d2003-10-13 22:26:55 +00003741 case SIOCGIFDSTADDR: /* get remote PA address */
3742 case SIOCGIFBRDADDR: /* get broadcast PA address */
thughesbe811712004-06-17 23:04:58 +00003743 case SIOCGIFNETMASK: /* get network PA mask */
thughes64326692004-09-11 15:14:59 +00003744 VG_TRACK( post_mem_write,
nethercotea8c1e922004-10-26 10:57:24 +00003745 (Addr)&((struct ifreq *)arg3)->ifr_addr,
thughes64326692004-09-11 15:14:59 +00003746 sizeof(((struct ifreq *)arg3)->ifr_addr) );
thughesbe811712004-06-17 23:04:58 +00003747 break;
3748 case SIOCGIFMETRIC: /* get metric */
thughes64326692004-09-11 15:14:59 +00003749 VG_TRACK( post_mem_write,
nethercotea8c1e922004-10-26 10:57:24 +00003750 (Addr)&((struct ifreq *)arg3)->ifr_metric,
thughes64326692004-09-11 15:14:59 +00003751 sizeof(((struct ifreq *)arg3)->ifr_metric) );
thughesbe811712004-06-17 23:04:58 +00003752 break;
3753 case SIOCGIFMAP: /* Get device parameters */
thughes64326692004-09-11 15:14:59 +00003754 VG_TRACK( post_mem_write,
nethercotea8c1e922004-10-26 10:57:24 +00003755 (Addr)&((struct ifreq *)arg3)->ifr_map,
thughes64326692004-09-11 15:14:59 +00003756 sizeof(((struct ifreq *)arg3)->ifr_map) );
thughesbe811712004-06-17 23:04:58 +00003757 break;
3758 break;
3759 case SIOCGIFTXQLEN: /* Get the tx queue length */
thughes64326692004-09-11 15:14:59 +00003760 VG_TRACK( post_mem_write,
nethercotea8c1e922004-10-26 10:57:24 +00003761 (Addr)&((struct ifreq *)arg3)->ifr_qlen,
thughes64326692004-09-11 15:14:59 +00003762 sizeof(((struct ifreq *)arg3)->ifr_qlen) );
thughesbe811712004-06-17 23:04:58 +00003763 break;
jsgf855d93d2003-10-13 22:26:55 +00003764 case SIOCGIFNAME: /* get iface name */
thughes64326692004-09-11 15:14:59 +00003765 VG_TRACK( post_mem_write,
nethercotea8c1e922004-10-26 10:57:24 +00003766 (Addr)&((struct ifreq *)arg3)->ifr_name,
thughes64326692004-09-11 15:14:59 +00003767 sizeof(((struct ifreq *)arg3)->ifr_name) );
jsgf855d93d2003-10-13 22:26:55 +00003768 break;
thughesbe811712004-06-17 23:04:58 +00003769#ifdef HAVE_LINUX_MII_H
3770 case SIOCGMIIPHY: /* get hardware entry */
thughes64326692004-09-11 15:14:59 +00003771 VG_TRACK( post_mem_write,
nethercotea8c1e922004-10-26 10:57:24 +00003772 (Addr)&((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->phy_id,
thughes64326692004-09-11 15:14:59 +00003773 sizeof(((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->phy_id) );
thughesbe811712004-06-17 23:04:58 +00003774 break;
3775 case SIOCGMIIREG: /* get hardware entry registers */
thughes64326692004-09-11 15:14:59 +00003776 VG_TRACK( post_mem_write,
nethercotea8c1e922004-10-26 10:57:24 +00003777 (Addr)&((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->val_out,
thughes64326692004-09-11 15:14:59 +00003778 sizeof(((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->val_out) );
thughesbe811712004-06-17 23:04:58 +00003779 break;
3780#endif
jsgf855d93d2003-10-13 22:26:55 +00003781 case SIOCGIFCONF: /* get iface list */
3782 /* WAS:
3783 SYSCALL_TRACK( pre_mem_write,"ioctl(SIOCGIFCONF)", arg3,
3784 sizeof(struct ifconf));
3785 KERNEL_DO_SYSCALL(tid,res);
3786 if (!VG_(is_kerror)(res) && res == 0)
3787 VG_TRACK( post_mem_write,arg3, sizeof(struct ifconf));
3788 */
3789 if (res == 0 && arg3 ) {
3790 struct ifconf *ifc = (struct ifconf *) arg3;
3791 if (ifc->ifc_buf != NULL)
3792 VG_TRACK( post_mem_write, (Addr)(ifc->ifc_buf),
3793 (UInt)(ifc->ifc_len) );
3794 }
3795 break;
3796 case SIOCGSTAMP:
thughes64326692004-09-11 15:14:59 +00003797 VG_TRACK( post_mem_write,arg3, sizeof(struct timeval));
jsgf855d93d2003-10-13 22:26:55 +00003798 break;
3799 /* SIOCOUTQ is an ioctl that, when called on a socket, returns
3800 the number of bytes currently in that socket's send buffer.
3801 It writes this value as an int to the memory location
3802 indicated by the third argument of ioctl(2). */
3803 case SIOCOUTQ:
thughes64326692004-09-11 15:14:59 +00003804 VG_TRACK( post_mem_write,arg3, sizeof(int));
jsgf855d93d2003-10-13 22:26:55 +00003805 break;
3806 case SIOCGRARP: /* get RARP table entry */
3807 case SIOCGARP: /* get ARP table entry */
thughes64326692004-09-11 15:14:59 +00003808 VG_TRACK( post_mem_write,arg3, sizeof(struct arpreq));
jsgf855d93d2003-10-13 22:26:55 +00003809 break;
3810
3811 case SIOCSIFFLAGS: /* set flags */
3812 case SIOCSIFMAP: /* Set device parameters */
3813 case SIOCSIFTXQLEN: /* Set the tx queue length */
3814 case SIOCSIFDSTADDR: /* set remote PA address */
3815 case SIOCSIFBRDADDR: /* set broadcast PA address */
3816 case SIOCSIFNETMASK: /* set network PA mask */
3817 case SIOCSIFMETRIC: /* set metric */
3818 case SIOCSIFADDR: /* set PA address */
3819 case SIOCSIFMTU: /* set MTU size */
3820 case SIOCSIFHWADDR: /* set hardware address */
thughesbe811712004-06-17 23:04:58 +00003821#ifdef HAVE_LINUX_MII_H
3822 case SIOCSMIIREG: /* set hardware entry registers */
3823#endif
jsgf855d93d2003-10-13 22:26:55 +00003824 break;
3825 /* Routing table calls. */
3826 case SIOCADDRT: /* add routing table entry */
3827 case SIOCDELRT: /* delete routing table entry */
3828 break;
3829
3830 /* RARP cache control calls. */
3831 case SIOCDRARP: /* delete RARP table entry */
3832 case SIOCSRARP: /* set RARP table entry */
3833 /* ARP cache control calls. */
3834 case SIOCSARP: /* set ARP table entry */
3835 case SIOCDARP: /* delete ARP table entry */
3836 break;
3837
thughes1174fed2004-09-11 15:33:17 +00003838 case SIOCGPGRP:
3839 VG_TRACK( post_mem_write,arg3, sizeof(int));
3840 break;
jsgf855d93d2003-10-13 22:26:55 +00003841 case SIOCSPGRP:
3842 break;
3843
3844 /* linux/soundcard interface (OSS) */
3845 case SNDCTL_SEQ_GETOUTCOUNT:
3846 case SNDCTL_SEQ_GETINCOUNT:
3847 case SNDCTL_SEQ_PERCMODE:
3848 case SNDCTL_SEQ_TESTMIDI:
3849 case SNDCTL_SEQ_RESETSAMPLES:
3850 case SNDCTL_SEQ_NRSYNTHS:
3851 case SNDCTL_SEQ_NRMIDIS:
3852 case SNDCTL_SEQ_GETTIME:
3853 case SNDCTL_DSP_GETFMTS:
3854 case SNDCTL_DSP_GETTRIGGER:
3855 case SNDCTL_DSP_GETODELAY:
3856# if defined(SNDCTL_DSP_GETSPDIF)
3857 case SNDCTL_DSP_GETSPDIF:
3858# endif
3859 case SNDCTL_DSP_GETCAPS:
3860 case SOUND_PCM_READ_RATE:
3861 case SOUND_PCM_READ_CHANNELS:
3862 case SOUND_PCM_READ_BITS:
3863 case (SOUND_PCM_READ_BITS|0x40000000): /* what the fuck ? */
3864 case SOUND_PCM_READ_FILTER:
thughes64326692004-09-11 15:14:59 +00003865 VG_TRACK( post_mem_write,arg3, sizeof(int));
jsgf855d93d2003-10-13 22:26:55 +00003866 break;
3867 case SNDCTL_SEQ_CTRLRATE:
3868 case SNDCTL_DSP_SPEED:
3869 case SNDCTL_DSP_STEREO:
3870 case SNDCTL_DSP_GETBLKSIZE:
3871 case SNDCTL_DSP_CHANNELS:
3872 case SOUND_PCM_WRITE_FILTER:
3873 case SNDCTL_DSP_SUBDIVIDE:
3874 case SNDCTL_DSP_SETFRAGMENT:
3875# if defined(SNDCTL_DSP_GETCHANNELMASK)
3876 case SNDCTL_DSP_GETCHANNELMASK:
3877# endif
3878# if defined(SNDCTL_DSP_BIND_CHANNEL)
3879 case SNDCTL_DSP_BIND_CHANNEL:
3880# endif
3881 case SNDCTL_TMR_TIMEBASE:
3882 case SNDCTL_TMR_TEMPO:
3883 case SNDCTL_TMR_SOURCE:
3884 case SNDCTL_MIDI_PRETIME:
3885 case SNDCTL_MIDI_MPUMODE:
3886 break;
3887 case SNDCTL_DSP_GETOSPACE:
3888 case SNDCTL_DSP_GETISPACE:
thughes64326692004-09-11 15:14:59 +00003889 VG_TRACK( post_mem_write,arg3, sizeof(audio_buf_info));
jsgf855d93d2003-10-13 22:26:55 +00003890 break;
3891 case SNDCTL_DSP_SETTRIGGER:
3892 break;
3893
3894 case SNDCTL_DSP_POST:
3895 case SNDCTL_DSP_RESET:
3896 case SNDCTL_DSP_SYNC:
3897 case SNDCTL_DSP_SETSYNCRO:
3898 case SNDCTL_DSP_SETDUPLEX:
3899 break;
3900
3901 /* Real Time Clock (/dev/rtc) ioctls */
3902# ifndef GLIBC_2_1
3903 case RTC_UIE_ON:
3904 case RTC_UIE_OFF:
3905 case RTC_AIE_ON:
3906 case RTC_AIE_OFF:
3907 case RTC_PIE_ON:
3908 case RTC_PIE_OFF:
3909 case RTC_IRQP_SET:
3910 break;
3911 case RTC_RD_TIME:
3912 case RTC_ALM_READ:
thughes64326692004-09-11 15:14:59 +00003913 VG_TRACK( post_mem_write,arg3, sizeof(struct rtc_time));
jsgf855d93d2003-10-13 22:26:55 +00003914 break;
3915 case RTC_ALM_SET:
3916 break;
3917 case RTC_IRQP_READ:
thughes64326692004-09-11 15:14:59 +00003918 VG_TRACK( post_mem_write,arg3, sizeof(unsigned long));
jsgf855d93d2003-10-13 22:26:55 +00003919 break;
3920# endif /* GLIBC_2_1 */
3921
3922# ifdef BLKGETSIZE
3923 case BLKGETSIZE:
thughes64326692004-09-11 15:14:59 +00003924 VG_TRACK( post_mem_write,arg3, sizeof(unsigned long));
jsgf855d93d2003-10-13 22:26:55 +00003925 break;
3926# endif /* BLKGETSIZE */
3927
thughesacbbc322004-06-19 12:12:01 +00003928 /* Hard disks */
3929 case HDIO_GET_IDENTITY: /* 0x030d */
thughes64326692004-09-11 15:14:59 +00003930 VG_TRACK( post_mem_write,arg3, sizeof(struct hd_driveid));
thughesacbbc322004-06-19 12:12:01 +00003931 break;
3932
jsgf855d93d2003-10-13 22:26:55 +00003933 /* CD ROM stuff (??) */
3934 case CDROMSUBCHNL:
thughes64326692004-09-11 15:14:59 +00003935 VG_TRACK( post_mem_write,arg3, sizeof(struct cdrom_subchnl));
jsgf855d93d2003-10-13 22:26:55 +00003936 break;
3937 case CDROMREADTOCHDR:
thughes64326692004-09-11 15:14:59 +00003938 VG_TRACK( post_mem_write,arg3, sizeof(struct cdrom_tochdr));
jsgf855d93d2003-10-13 22:26:55 +00003939 break;
3940 case CDROMREADTOCENTRY:
thughes64326692004-09-11 15:14:59 +00003941 VG_TRACK( post_mem_write,arg3, sizeof(struct cdrom_tochdr));
jsgf855d93d2003-10-13 22:26:55 +00003942 break;
thughes5b788fb2004-09-11 15:07:14 +00003943 case CDROMMULTISESSION:
3944 VG_TRACK( post_mem_write,arg3, sizeof(struct cdrom_multisession));
3945 break;
3946 case CDROMVOLREAD:
3947 VG_TRACK( post_mem_write,arg3, sizeof(struct cdrom_volctrl));
3948 break;
3949 case CDROMREADAUDIO:
3950 {
3951 struct cdrom_read_audio *cra = (struct cdrom_read_audio *) arg3;
3952 VG_TRACK( post_mem_write, (Addr)(cra->buf),
3953 (UInt)(cra->nframes * CD_FRAMESIZE_RAW));
3954 break;
3955 }
3956
jsgf855d93d2003-10-13 22:26:55 +00003957 case CDROMPLAYMSF:
3958 break;
3959 /* The following two are probably bogus (should check args
3960 for readability). JRS 20021117 */
3961 case CDROM_DRIVE_STATUS: /* 0x5326 */
3962 case CDROM_CLEAR_OPTIONS: /* 0x5321 */
3963 break;
3964
thughes66d80092004-06-19 12:41:05 +00003965 case FIGETBSZ:
thughes64326692004-09-11 15:14:59 +00003966 VG_TRACK( post_mem_write,arg3, sizeof(unsigned long));
thughes66d80092004-06-19 12:41:05 +00003967 break;
3968 case FIBMAP:
thughes64326692004-09-11 15:14:59 +00003969 VG_TRACK( post_mem_write,arg3, sizeof(unsigned long));
thughes66d80092004-06-19 12:41:05 +00003970 break;
3971
thughes1742d6f2004-04-22 07:28:43 +00003972#ifdef HAVE_LINUX_FB_H
thughes44e35582004-04-21 15:52:33 +00003973 case FBIOGET_VSCREENINFO: //0x4600
thughes64326692004-09-11 15:14:59 +00003974 VG_TRACK( post_mem_write,arg3, sizeof(struct fb_var_screeninfo));
thughes44e35582004-04-21 15:52:33 +00003975 break;
3976 case FBIOGET_FSCREENINFO: //0x4602
thughes64326692004-09-11 15:14:59 +00003977 VG_TRACK( post_mem_write,arg3, sizeof(struct fb_fix_screeninfo));
thughes44e35582004-04-21 15:52:33 +00003978 break;
thughes1742d6f2004-04-22 07:28:43 +00003979#endif
thughes44e35582004-04-21 15:52:33 +00003980
thughesd9895482004-08-16 19:46:55 +00003981 case PPCLAIM:
3982 case PPEXCL:
3983 case PPYIELD:
3984 case PPRELEASE:
3985 case PPSETMODE:
3986 case PPSETPHASE:
thughesfb6f2002004-09-01 07:29:08 +00003987#ifdef PPSETFLAGS
thughesd9895482004-08-16 19:46:55 +00003988 case PPSETFLAGS:
thughesfb6f2002004-09-01 07:29:08 +00003989#endif
thughesd9895482004-08-16 19:46:55 +00003990 case PPWDATA:
3991 case PPWCONTROL:
3992 case PPFCONTROL:
3993 case PPDATADIR:
3994 case PPNEGOT:
3995 case PPWCTLONIRQ:
3996 case PPSETTIME:
3997 break;
thughesfb6f2002004-09-01 07:29:08 +00003998#ifdef PPGETMODE
thughesd9895482004-08-16 19:46:55 +00003999 case PPGETMODE:
4000 VG_TRACK( post_mem_write, arg3, sizeof(int) );
4001 break;
thughesfb6f2002004-09-01 07:29:08 +00004002#endif
4003#ifdef PPGETPHASE
thughesd9895482004-08-16 19:46:55 +00004004 case PPGETPHASE:
4005 VG_TRACK( post_mem_write, arg3, sizeof(int) );
4006 break;
thughesfb6f2002004-09-01 07:29:08 +00004007#endif
4008#ifdef PPGETMODES
thughesd9895482004-08-16 19:46:55 +00004009 case PPGETMODES:
4010 VG_TRACK( post_mem_write, arg3, sizeof(unsigned int) );
4011 break;
thughesfb6f2002004-09-01 07:29:08 +00004012#endif
4013#ifdef PPGETFLAGS
thughesd9895482004-08-16 19:46:55 +00004014 case PPGETFLAGS:
4015 VG_TRACK( post_mem_write, arg3, sizeof(int) );
4016 break;
thughesfb6f2002004-09-01 07:29:08 +00004017#endif
thughesd9895482004-08-16 19:46:55 +00004018 case PPRSTATUS:
4019 VG_TRACK( post_mem_write, arg3, sizeof(unsigned char) );
4020 break;
4021 case PPRDATA:
4022 VG_TRACK( post_mem_write, arg3, sizeof(unsigned char) );
4023 break;
4024 case PPRCONTROL:
4025 VG_TRACK( post_mem_write, arg3, sizeof(unsigned char) );
4026 break;
4027 case PPCLRIRQ:
4028 VG_TRACK( post_mem_write, arg3, sizeof(int) );
4029 break;
4030 case PPGETTIME:
4031 VG_TRACK( post_mem_write, arg3, sizeof(struct timeval) );
4032 break;
4033
jsgf855d93d2003-10-13 22:26:55 +00004034 /* We don't have any specific information on it, so
4035 try to do something reasonable based on direction and
4036 size bits. The encoding scheme is described in
4037 /usr/include/asm/ioctl.h.
4038
4039 According to Simon Hausmann, _IOC_READ means the kernel
4040 writes a value to the ioctl value passed from the user
4041 space and the other way around with _IOC_WRITE. */
4042 default: {
4043 UInt dir = _IOC_DIR(arg2);
4044 UInt size = _IOC_SIZE(arg2);
4045 if (size > 0 && (dir & _IOC_READ)
4046 && res == 0
4047 && arg3 != (Addr)NULL)
4048 VG_TRACK( post_mem_write,arg3, size);
4049 break;
4050 }
4051 }
4052}
4053
4054PRE(kill)
4055{
4056 /* int kill(pid_t pid, int sig); */
4057 MAYBE_PRINTF("kill ( %d, %d )\n", arg1,arg2);
4058 if (arg2 == VKI_SIGVGINT || arg2 == VKI_SIGVGKILL)
nethercote35122912004-10-18 17:00:30 +00004059 set_result( -VKI_EINVAL );
jsgf855d93d2003-10-13 22:26:55 +00004060}
4061
4062POST(kill)
4063{
4064 /* If this was a self-kill then wait for a signal to be
4065 delivered to any thread before claiming the kill is done. */
4066 if (res >= 0 && /* if it was successful */
4067 arg2 != 0 && /* if a real signal */
4068 !VG_(is_sig_ign)(arg2) && /* that isn't ignored and */
4069 !VG_(ksigismember)(&tst->eff_sig_mask, arg2) && /* we're not blocking it */
4070 (arg1 == VG_(getpid)() || /* directed at us or */
4071 arg1 == -1 || /* directed at everyone or */
4072 arg1 == 0 || /* directed at whole group or */
4073 -arg1 == VG_(getpgrp)())) { /* directed at our group... */
4074 /* ...then wait for that signal to be delivered to someone
4075 (might be us, might be someone else who doesn't have it
4076 blocked) */
4077 VG_(proxy_waitsig)();
4078 }
4079}
4080
4081PRE(link)
4082{
4083 /* int link(const char *oldpath, const char *newpath); */
4084 MAYBE_PRINTF("link ( %p, %p)\n", arg1, arg2);
4085 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "link(oldpath)", arg1);
4086 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "link(newpath)", arg2);
4087}
4088
4089PRE(lseek)
4090{
4091 /* off_t lseek(int fildes, off_t offset, int whence); */
4092 MAYBE_PRINTF("lseek ( %d, %d, %d )\n",arg1,arg2,arg3);
4093}
4094
4095PRE(_llseek)
4096{
4097 /* int _llseek(unsigned int fd, unsigned long offset_high,
4098 unsigned long offset_low,
4099 loff_t * result, unsigned int whence); */
4100 MAYBE_PRINTF("llseek ( %d, 0x%x, 0x%x, %p, %d )\n",
4101 arg1,arg2,arg3,arg4,arg5);
4102 SYSCALL_TRACK( pre_mem_write, tid, "llseek(result)", arg4,
4103 sizeof(loff_t));
4104}
4105
4106POST(_llseek)
4107{
4108 if (res == 0)
4109 VG_TRACK( post_mem_write, arg4, sizeof(loff_t) );
4110}
4111
4112PRE(lstat)
4113{
4114 /* int lstat(const char *file_name, struct stat *buf); */
nethercotee70bd7d2004-08-18 14:37:17 +00004115 MAYBE_PRINTF("lstat ( %p(%s), %p )\n",arg1,arg1,arg2);
jsgf855d93d2003-10-13 22:26:55 +00004116 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "lstat(file_name)", arg1 );
4117 SYSCALL_TRACK( pre_mem_write, tid, "lstat(buf)", arg2,
4118 sizeof(struct stat) );
4119}
4120
4121POST(lstat)
4122{
4123 if (res == 0) {
4124 VG_TRACK( post_mem_write, arg2, sizeof(struct stat) );
4125 }
4126}
4127
4128PRE(lstat64)
4129{
4130 /* int lstat64(const char *file_name, struct stat64 *buf); */
nethercotee70bd7d2004-08-18 14:37:17 +00004131 MAYBE_PRINTF("lstat64 ( %p(%s), %p )\n",arg1,arg1,arg2);
jsgf855d93d2003-10-13 22:26:55 +00004132 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "lstat64(file_name)", arg1 );
4133 SYSCALL_TRACK( pre_mem_write, tid, "lstat64(buf)", arg2,
4134 sizeof(struct stat64) );
4135}
4136
4137POST(lstat64)
4138{
4139 if (res == 0) {
4140 VG_TRACK( post_mem_write, arg2, sizeof(struct stat64) );
4141 }
4142}
4143
4144PRE(mkdir)
4145{
4146 /* int mkdir(const char *pathname, mode_t mode); */
4147 MAYBE_PRINTF("mkdir ( %p, %d )\n", arg1,arg2);
4148 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "mkdir(pathname)", arg1 );
4149}
4150
4151PRE(mmap2)
4152{
nethercote27ea8bc2004-07-10 17:21:14 +00004153 // Exactly like __NR_mmap except:
4154 // - all 6 args are passed in regs, rather than in a memory-block.
4155 // - the file offset is specified in pagesize units rather than bytes,
4156 // so that it can be used for files bigger than 2^32 bytes.
jsgf855d93d2003-10-13 22:26:55 +00004157 /* void* mmap(void *start, size_t length, int prot,
4158 int flags, int fd, off_t offset);
4159 */
4160 MAYBE_PRINTF("mmap2 ( %p, %d, %d, %d, %d, %d )\n",
4161 arg1, arg2, arg3, arg4, arg5, arg6 );
nethercotedb233322003-12-02 14:56:04 +00004162
fitzhardinge98abfc72003-12-16 02:05:15 +00004163 if (arg4 & VKI_MAP_FIXED) {
4164 if (!valid_client_addr(arg1, arg2, tid, "mmap2"))
nethercote35122912004-10-18 17:00:30 +00004165 set_result( -VKI_ENOMEM );
fitzhardinge98abfc72003-12-16 02:05:15 +00004166 } else {
4167 arg1 = VG_(find_map_space)(arg1, arg2, True);
fitzhardinge98abfc72003-12-16 02:05:15 +00004168 if (arg1 == 0)
nethercote35122912004-10-18 17:00:30 +00004169 set_result( -VKI_ENOMEM );
nethercote27ea8bc2004-07-10 17:21:14 +00004170 else
4171 arg4 |= VKI_MAP_FIXED;
fitzhardinge98abfc72003-12-16 02:05:15 +00004172 }
jsgf855d93d2003-10-13 22:26:55 +00004173}
4174
4175POST(mmap2)
4176{
nethercotefe082612004-07-10 18:08:13 +00004177 vg_assert(valid_client_addr(res, arg2, tid, "mmap2"));
4178 mmap_segment( (Addr)res, arg2, arg3, arg4, arg5, arg6 * (ULong)VKI_BYTES_PER_PAGE );
jsgf855d93d2003-10-13 22:26:55 +00004179}
4180
4181PRE(mmap)
4182{
4183 /* void* mmap(void *start, size_t length, int prot,
4184 int flags, int fd, off_t offset);
4185 */
4186
jsgf855d93d2003-10-13 22:26:55 +00004187 UInt a1, a2, a3, a4, a5, a6;
4188
nethercote6456ab12004-10-18 14:47:48 +00004189 vg_assert(tid = tst->tid);
4190 PLATFORM_GET_MMAP_ARGS(tst, a1, a2, a3, a4, a5, a6);
jsgf855d93d2003-10-13 22:26:55 +00004191
jsgf855d93d2003-10-13 22:26:55 +00004192 MAYBE_PRINTF("mmap ( %p, %d, %d, %d, %d, %d )\n",
4193 a1, a2, a3, a4, a5, a6 );
nethercotedb233322003-12-02 14:56:04 +00004194
fitzhardinge98abfc72003-12-16 02:05:15 +00004195 if (a4 & VKI_MAP_FIXED) {
4196 if (!valid_client_addr(a1, a2, tid, "mmap")) {
4197 MAYBE_PRINTF("mmap failing: %p-%p\n", a1, a1+a2);
nethercote35122912004-10-18 17:00:30 +00004198 set_result( -VKI_ENOMEM );
fitzhardinge98abfc72003-12-16 02:05:15 +00004199 }
4200 } else {
nethercote6456ab12004-10-18 14:47:48 +00004201 a1 = VG_(find_map_space)(a1, a2, True);
fitzhardinge98abfc72003-12-16 02:05:15 +00004202 if (a1 == 0)
nethercote35122912004-10-18 17:00:30 +00004203 set_result( -VKI_ENOMEM );
fitzhardinge98abfc72003-12-16 02:05:15 +00004204 else
4205 a4 |= VKI_MAP_FIXED;
4206 }
jsgf855d93d2003-10-13 22:26:55 +00004207
fitzhardinge98abfc72003-12-16 02:05:15 +00004208 if (res != -VKI_ENOMEM) {
nethercote6456ab12004-10-18 14:47:48 +00004209 PLATFORM_DO_MMAP(res, a1, a2, a3, a4, a5, a6);
fitzhardingec2d65072004-01-07 08:44:43 +00004210
4211 if (!VG_(is_kerror)(res)) {
nethercoteb4250ae2004-07-10 16:50:09 +00004212 vg_assert(valid_client_addr(res, a2, tid, "mmap"));
4213 mmap_segment( (Addr)res, a2, a3, a4, a5, a6 );
fitzhardingec2d65072004-01-07 08:44:43 +00004214 }
fitzhardinge98abfc72003-12-16 02:05:15 +00004215 }
jsgf855d93d2003-10-13 22:26:55 +00004216}
4217
4218PRE(mprotect)
4219{
4220 /* int mprotect(const void *addr, size_t len, int prot); */
4221 /* should addr .. addr+len-1 be checked before the call? */
4222 MAYBE_PRINTF("mprotect ( %p, %d, %d )\n", arg1,arg2,arg3);
fitzhardinge98abfc72003-12-16 02:05:15 +00004223
4224 if (!valid_client_addr(arg1, arg2, tid, "mprotect"))
nethercote35122912004-10-18 17:00:30 +00004225 set_result( -VKI_ENOMEM );
jsgf855d93d2003-10-13 22:26:55 +00004226}
4227
4228POST(mprotect)
4229{
nethercote27ea8bc2004-07-10 17:21:14 +00004230 Addr a = arg1;
4231 UInt len = arg2;
4232 Int prot = arg3;
4233 Bool rr = prot & VKI_PROT_READ;
4234 Bool ww = prot & VKI_PROT_WRITE;
4235 Bool xx = prot & VKI_PROT_EXEC;
4236
nethercote27ea8bc2004-07-10 17:21:14 +00004237 mash_addr_and_len(&a, &len);
4238 VG_(mprotect_range)(a, len, prot);
4239 VG_TRACK( change_mem_mprotect, a, len, rr, ww, xx );
jsgf855d93d2003-10-13 22:26:55 +00004240}
4241
4242PRE(munmap)
4243{
4244 /* int munmap(void *start, size_t length); */
4245 /* should start .. start+length-1 be checked before the call? */
4246 MAYBE_PRINTF("munmap ( %p, %d )\n", arg1,arg2);
fitzhardinge98abfc72003-12-16 02:05:15 +00004247
4248 if (!valid_client_addr(arg1, arg2, tid, "munmap"))
nethercote35122912004-10-18 17:00:30 +00004249 set_result( -VKI_EINVAL );
jsgf855d93d2003-10-13 22:26:55 +00004250}
4251
4252POST(munmap)
4253{
nethercote27ea8bc2004-07-10 17:21:14 +00004254 Addr a = arg1;
4255 UInt len = arg2;
4256
4257 mash_addr_and_len(&a, &len);
4258 VG_(unmap_range)(a, len);
4259 VG_TRACK( die_mem_munmap, a, len );
jsgf855d93d2003-10-13 22:26:55 +00004260}
4261
mueller6ceb2312004-01-02 22:52:34 +00004262PRE(mincore)
4263{
4264 /* int mincore(void *start, size_t length, unsigned char *vec); */
4265 MAYBE_PRINTF("mincore ( %p, %d, %p )\n", arg1,arg2,arg3);
4266 SYSCALL_TRACK(pre_mem_write, tid, "mincore(vec)",
4267 arg3, (arg2 + 4096 - 1) / 4096);
4268}
4269
4270POST(mincore)
4271{
nethercotefe082612004-07-10 18:08:13 +00004272 VG_TRACK( post_mem_write, arg3, (arg2 + 4096 - 1) / 4096 );
mueller6ceb2312004-01-02 22:52:34 +00004273}
4274
jsgf855d93d2003-10-13 22:26:55 +00004275PRE(nanosleep)
4276{
nethercotefe082612004-07-10 18:08:13 +00004277 /* int nanosleep(const struct timespec *req, struct timespec *rem); */
4278 MAYBE_PRINTF("nanosleep ( %p, %p )\n", arg1,arg2);
4279 SYSCALL_TRACK( pre_mem_read, tid, "nanosleep(req)", arg1,
4280 sizeof(struct timespec) );
4281 if (arg2 != (UInt)NULL)
4282 SYSCALL_TRACK( pre_mem_write, tid, "nanosleep(rem)", arg2,
4283 sizeof(struct timespec) );
jsgf855d93d2003-10-13 22:26:55 +00004284}
4285
4286POST(nanosleep)
4287{
thughesbaa46e52004-07-29 17:44:23 +00004288 if (arg2 != (UInt)NULL && res == -VKI_EINTR)
jsgf855d93d2003-10-13 22:26:55 +00004289 VG_TRACK( post_mem_write, arg2, sizeof(struct timespec) );
4290}
4291
4292PRE(_newselect)
4293{
4294 /* int select(int n,
4295 fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
4296 struct timeval *timeout);
4297 */
4298 MAYBE_PRINTF("newselect ( %d, %p, %p, %p, %p )\n",
4299 arg1,arg2,arg3,arg4,arg5);
4300 if (arg2 != 0)
4301 SYSCALL_TRACK( pre_mem_read, tid, "newselect(readfds)",
4302 arg2, arg1/8 /* __FD_SETSIZE/8 */ );
4303 if (arg3 != 0)
4304 SYSCALL_TRACK( pre_mem_read, tid, "newselect(writefds)",
4305 arg3, arg1/8 /* __FD_SETSIZE/8 */ );
4306 if (arg4 != 0)
4307 SYSCALL_TRACK( pre_mem_read, tid, "newselect(exceptfds)",
4308 arg4, arg1/8 /* __FD_SETSIZE/8 */ );
4309 if (arg5 != 0)
4310 SYSCALL_TRACK( pre_mem_read, tid, "newselect(timeout)", arg5,
4311 sizeof(struct timeval) );
4312}
4313
4314PRE(open)
4315{
nethercotee70bd7d2004-08-18 14:37:17 +00004316 /* int open(const char *pathname, int flags, mode_t mode); */
4317 if (arg2 & VKI_O_CREAT) {
4318 /* int open(const char *pathname, int flags, mode_t mode); */
4319 MAYBE_PRINTF("open ( %p(%s), %d, %d ) --> ",arg1,arg1,arg2,arg3);
4320 } else {
4321 /* int open(const char *pathname, int flags); */
4322 MAYBE_PRINTF("open ( %p(%s), %d ) --> ",arg1,arg1,arg2);
4323 }
jsgf855d93d2003-10-13 22:26:55 +00004324 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "open(pathname)", arg1 );
4325}
4326
4327POST(open)
4328{
thughesad1c9562004-06-26 11:27:52 +00004329 if (!fd_allowed(res, "open", tid, True)) {
jsgf855d93d2003-10-13 22:26:55 +00004330 VG_(close)(res);
nethercote35122912004-10-18 17:00:30 +00004331 set_result( -VKI_EMFILE );
rjwalshf5f536f2003-11-17 17:45:00 +00004332 } else {
nethercote493dd182004-02-24 23:57:47 +00004333 if (VG_(clo_track_fds))
fitzhardingea7728472003-12-16 01:48:38 +00004334 record_fd_open(tid, res, VG_(arena_strdup)(VG_AR_CORE, (Char*)arg1));
jsgf855d93d2003-10-13 22:26:55 +00004335 }
4336 MAYBE_PRINTF("%d\n",res);
4337}
4338
4339PRE(read)
4340{
4341 /* size_t read(int fd, void *buf, size_t count); */
4342 MAYBE_PRINTF("read ( %d, %p, %d )\n", arg1, arg2, arg3);
4343
thughesad1c9562004-06-26 11:27:52 +00004344 if (!fd_allowed(arg1, "read", tid, False))
nethercote35122912004-10-18 17:00:30 +00004345 set_result( -VKI_EBADF );
thughes26ab77b2004-08-14 12:10:49 +00004346 else
4347 SYSCALL_TRACK( pre_mem_write, tid, "read(buf)", arg2, arg3 );
jsgf855d93d2003-10-13 22:26:55 +00004348}
4349
4350POST(read)
4351{
thughes26ab77b2004-08-14 12:10:49 +00004352 VG_TRACK( post_mem_write, arg2, res );
jsgf855d93d2003-10-13 22:26:55 +00004353}
4354
4355PRE(write)
4356{
4357 /* size_t write(int fd, const void *buf, size_t count); */
4358 MAYBE_PRINTF("write ( %d, %p, %d )\n", arg1, arg2, arg3);
thughesad1c9562004-06-26 11:27:52 +00004359 if (!fd_allowed(arg1, "write", tid, False))
nethercote35122912004-10-18 17:00:30 +00004360 set_result( -VKI_EBADF );
jsgf855d93d2003-10-13 22:26:55 +00004361 else
4362 SYSCALL_TRACK( pre_mem_read, tid, "write(buf)", arg2, arg3 );
4363}
4364
4365PRE(creat)
4366{
4367 /* int creat(const char *pathname, mode_t mode); */
4368 MAYBE_PRINTF("creat ( %p(%s), %d ) --> ",arg1,arg1,arg2);
4369 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "creat(pathname)", arg1 );
4370}
4371
4372POST(creat)
4373{
thughesad1c9562004-06-26 11:27:52 +00004374 if (!fd_allowed(res, "creat", tid, True)) {
jsgf855d93d2003-10-13 22:26:55 +00004375 VG_(close)(res);
nethercote35122912004-10-18 17:00:30 +00004376 set_result( -VKI_EMFILE );
rjwalshf5f536f2003-11-17 17:45:00 +00004377 } else {
nethercote493dd182004-02-24 23:57:47 +00004378 if (VG_(clo_track_fds))
fitzhardingea7728472003-12-16 01:48:38 +00004379 record_fd_open(tid, res, VG_(arena_strdup)(VG_AR_CORE, (Char*)arg1));
jsgf855d93d2003-10-13 22:26:55 +00004380 }
4381 MAYBE_PRINTF("%d\n",res);
4382}
4383
4384PRE(pipe)
4385{
4386 /* int pipe(int filedes[2]); */
4387 MAYBE_PRINTF("pipe ( %p ) ...\n", arg1);
4388 SYSCALL_TRACK( pre_mem_write, tid, "pipe(filedes)",
4389 arg1, 2*sizeof(int) );
4390}
4391
4392POST(pipe)
4393{
4394 Int *p = (Int *)arg1;
4395
thughesad1c9562004-06-26 11:27:52 +00004396 if (!fd_allowed(p[0], "pipe", tid, True) ||
4397 !fd_allowed(p[1], "pipe", tid, True)) {
jsgf855d93d2003-10-13 22:26:55 +00004398 VG_(close)(p[0]);
4399 VG_(close)(p[1]);
nethercote35122912004-10-18 17:00:30 +00004400 set_result( -VKI_EMFILE );
rjwalshf5f536f2003-11-17 17:45:00 +00004401 } else {
jsgf855d93d2003-10-13 22:26:55 +00004402 VG_TRACK( post_mem_write, arg1, 2*sizeof(int) );
nethercote493dd182004-02-24 23:57:47 +00004403 if (VG_(clo_track_fds)) {
rjwalshf5f536f2003-11-17 17:45:00 +00004404 record_fd_open(tid, p[0], NULL);
4405 record_fd_open(tid, p[1], NULL);
4406 }
4407 }
jsgf855d93d2003-10-13 22:26:55 +00004408
4409 MAYBE_PRINTF("SYSCALL[%d] pipe --> %d (rd %d, wr %d)\n",
4410 VG_(getpid)(), res,
4411 ((UInt*)arg1)[0], ((UInt*)arg1)[1] );
4412}
4413
4414PRE(poll)
4415{
4416 /* struct pollfd {
4417 int fd; -- file descriptor
4418 short events; -- requested events
4419 short revents; -- returned events
4420 };
4421 int poll(struct pollfd *ufds, unsigned int nfds,
4422 int timeout)
4423 */
4424 MAYBE_PRINTF("poll ( %p, %d, %d )\n",arg1,arg2,arg3);
4425 /* In fact some parts of this struct should be readable too.
4426 This should be fixed properly. */
4427 SYSCALL_TRACK( pre_mem_write, tid, "poll(ufds)",
4428 arg1, arg2 * sizeof(struct pollfd) );
4429}
4430
4431POST(poll)
4432{
4433 if (res > 0) {
4434 UInt i;
4435 struct pollfd * arr = (struct pollfd *)arg1;
4436 for (i = 0; i < arg2; i++)
4437 VG_TRACK( post_mem_write, (Addr)(&arr[i].revents),
4438 sizeof(Short) );
4439 }
4440}
4441
nethercote9af69b32004-02-10 23:44:15 +00004442PRE(epoll_create)
4443{
4444 /* int epoll_create(int size) */
4445 MAYBE_PRINTF("epoll_create ( %d )\n", arg1);
4446}
4447
4448POST(epoll_create)
4449{
thughesad1c9562004-06-26 11:27:52 +00004450 if (!fd_allowed(res, "open", tid, True)) {
nethercote9af69b32004-02-10 23:44:15 +00004451 VG_(close)(res);
nethercote35122912004-10-18 17:00:30 +00004452 set_result( -VKI_EMFILE );
nethercote9af69b32004-02-10 23:44:15 +00004453 } else {
4454 if (VG_(clo_track_fds))
4455 record_fd_open (tid, res, NULL);
4456 }
4457}
4458
4459PRE(epoll_ctl)
4460{
4461 /* int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) */
4462 static const char* epoll_ctl_s[3] = {
4463 "EPOLL_CTL_ADD",
4464 "EPOLL_CTL_DEL",
4465 "EPOLL_CTL_MOD"
4466 };
4467 MAYBE_PRINTF("epoll_ctl ( %d, %s, %d, %p )\n",
4468 arg1, ( arg2<3 ? epoll_ctl_s[arg2] : "?" ), arg3, arg4);
4469 SYSCALL_TRACK( pre_mem_read, tid, "epoll_ctl(event)",
4470 arg4, sizeof(struct vki_epoll_event) );
4471}
4472
4473PRE(epoll_wait)
4474{
4475 /* int epoll_wait(int epfd, struct epoll_event * events,
4476 int maxevents, int timeout) */
4477 MAYBE_PRINTF("epoll_wait ( %d, %p, %d, %d )\n", arg1, arg2, arg3, arg4);
4478 SYSCALL_TRACK( pre_mem_write, tid, "epoll_wait(events)",
4479 arg2, sizeof(struct vki_epoll_event)*arg3);
4480}
4481
4482POST(epoll_wait)
4483{
4484 if (res > 0)
4485 VG_TRACK( post_mem_write, arg2, sizeof(struct vki_epoll_event)*res ) ;
4486}
4487
jsgf855d93d2003-10-13 22:26:55 +00004488PRE(readlink)
4489{
4490 /* int readlink(const char *path, char *buf, size_t bufsiz); */
4491 MAYBE_PRINTF("readlink ( %p, %p, %d )\n", arg1,arg2,arg3);
4492 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "readlink(path)", arg1 );
4493 SYSCALL_TRACK( pre_mem_write, tid, "readlink(buf)", arg2,arg3 );
4494}
4495
4496POST(readlink)
4497{
4498 VG_TRACK( post_mem_write, arg2, res );
4499}
4500
4501PRE(readv)
4502{
4503 /* int readv(int fd, const struct iovec * vector, size_t count); */
4504 Int i;
4505 struct iovec * vec;
4506 MAYBE_PRINTF("readv ( %d, %p, %d )\n",arg1,arg2,arg3);
thughesad1c9562004-06-26 11:27:52 +00004507 if (!fd_allowed(arg1, "readv", tid, False)) {
nethercote35122912004-10-18 17:00:30 +00004508 set_result( -VKI_EBADF );
jsgf855d93d2003-10-13 22:26:55 +00004509 } else {
4510 SYSCALL_TRACK( pre_mem_read, tid, "readv(vector)",
4511 arg2, arg3 * sizeof(struct iovec) );
4512 /* ToDo: don't do any of the following if the vector is invalid */
4513 vec = (struct iovec *)arg2;
4514 for (i = 0; i < (Int)arg3; i++)
4515 SYSCALL_TRACK( pre_mem_write, tid, "readv(vector[...])",
nethercotea8c1e922004-10-26 10:57:24 +00004516 (Addr)vec[i].iov_base, vec[i].iov_len );
jsgf855d93d2003-10-13 22:26:55 +00004517 }
4518}
4519
4520POST(readv)
4521{
4522 if (res > 0) {
4523 Int i;
4524 struct iovec * vec = (struct iovec *)arg2;
4525 Int remains = res;
4526
4527 /* res holds the number of bytes read. */
4528 for (i = 0; i < (Int)arg3; i++) {
4529 Int nReadThisBuf = vec[i].iov_len;
4530 if (nReadThisBuf > remains) nReadThisBuf = remains;
nethercotea8c1e922004-10-26 10:57:24 +00004531 VG_TRACK( post_mem_write, (Addr)vec[i].iov_base, nReadThisBuf );
jsgf855d93d2003-10-13 22:26:55 +00004532 remains -= nReadThisBuf;
4533 if (remains < 0) VG_(core_panic)("readv: remains < 0");
4534 }
4535 }
4536}
4537
4538PRE(rename)
4539{
4540 /* int rename(const char *oldpath, const char *newpath); */
4541 MAYBE_PRINTF("rename ( %p, %p )\n", arg1, arg2 );
4542 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "rename(oldpath)", arg1 );
4543 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "rename(newpath)", arg2 );
4544}
4545
4546PRE(rmdir)
4547{
4548 /* int rmdir(const char *pathname); */
4549 MAYBE_PRINTF("rmdir ( %p )\n", arg1);
4550 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "rmdir(pathname)", arg1 );
4551}
4552
4553PRE(sched_setparam)
4554{
4555 /* int sched_setparam(pid_t pid, const struct sched_param *p); */
4556 MAYBE_PRINTF("sched_setparam ( %d, %p )\n", arg1, arg2 );
4557 SYSCALL_TRACK( pre_mem_read, tid, "sched_setparam(ptr)",
4558 arg2, sizeof(struct sched_param) );
4559}
4560
4561POST(sched_setparam)
4562{
4563 VG_TRACK( post_mem_write, arg2, sizeof(struct sched_param) );
4564}
4565
4566PRE(sched_getparam)
4567{
4568 /* int sched_getparam(pid_t pid, struct sched_param *p); */
4569 MAYBE_PRINTF("sched_getparam ( %d, %p )\n", arg1, arg2 );
4570 SYSCALL_TRACK( pre_mem_write, tid, "sched_getparam(ptr)",
4571 arg2, sizeof(struct sched_param) );
4572}
4573
4574POST(sched_getparam)
4575{
4576 VG_TRACK( post_mem_write, arg2, sizeof(struct sched_param) );
4577}
4578
4579PRE(sched_yield)
4580{
4581 /* int sched_yield(void); */
4582 MAYBE_PRINTF("sched_yield ()\n" );
4583}
4584
4585PRE(select)
4586{
4587 /* struct sel_arg_struct {
4588 unsigned long n;
4589 fd_set *inp, *outp, *exp;
4590 struct timeval *tvp;
4591 };
4592 int old_select(struct sel_arg_struct *arg);
4593 */
4594 SYSCALL_TRACK( pre_mem_read, tid, "select(args)", arg1, 5*sizeof(UInt) );
4595
4596 {
4597 UInt* arg_struct = (UInt*)arg1;
4598 UInt a1, a2, a3, a4, a5;
4599
4600 a1 = arg_struct[0];
4601 a2 = arg_struct[1];
4602 a3 = arg_struct[2];
4603 a4 = arg_struct[3];
4604 a5 = arg_struct[4];
4605
4606 MAYBE_PRINTF("select ( %d, %p, %p, %p, %p )\n",
4607 a1,a2,a3,a4,a5);
4608 if (a2 != (Addr)NULL)
4609 SYSCALL_TRACK( pre_mem_read, tid, "select(readfds)", a2,
4610 a1/8 /* __FD_SETSIZE/8 */ );
4611 if (a3 != (Addr)NULL)
4612 SYSCALL_TRACK( pre_mem_read, tid, "select(writefds)", a3,
nethercotea4c33c62004-02-15 15:10:25 +00004613 a1/8 /* __FD_SETSIZE/8 */ );
jsgf855d93d2003-10-13 22:26:55 +00004614 if (a4 != (Addr)NULL)
4615 SYSCALL_TRACK( pre_mem_read, tid, "select(exceptfds)", a4,
4616 a1/8 /* __FD_SETSIZE/8 */ );
4617 if (a5 != (Addr)NULL)
4618 SYSCALL_TRACK( pre_mem_read, tid, "select(timeout)", a5,
4619 sizeof(struct timeval) );
4620 }
4621}
4622
4623PRE(setitimer)
4624{
4625 /* setitimer(int which, const struct itimerval *value,
4626 struct itimerval *ovalue); */
4627 MAYBE_PRINTF("setitimer ( %d, %p, %p )\n", arg1,arg2,arg3);
4628 if (arg2 != (Addr)NULL)
4629 SYSCALL_TRACK( pre_mem_read,tid, "setitimer(value)",
4630 arg2, sizeof(struct itimerval) );
4631 if (arg3 != (Addr)NULL)
4632 SYSCALL_TRACK( pre_mem_write,tid, "setitimer(ovalue)",
4633 arg3, sizeof(struct itimerval));
4634}
4635
4636POST(setitimer)
4637{
4638 if (arg3 != (Addr)NULL) {
4639 VG_TRACK( post_mem_write,arg3, sizeof(struct itimerval));
4640 }
4641}
4642
4643PRE(setfsgid32)
4644{
4645 /* int setfsgid(uid_t fsgid); */
4646 MAYBE_PRINTF("setfsgid ( %d )\n", arg1);
4647}
4648
4649PRE(setgid)
4650{
4651 /* int setgid(gid_t gid); */
4652 MAYBE_PRINTF("setgid ( %d )\n", arg1);
4653}
4654
4655PREALIAS(setgid32, setgid);
4656
4657PRE(setsid)
4658{
4659 /* pid_t setsid(void); */
4660 MAYBE_PRINTF("setsid ()\n");
4661}
4662
4663PRE(setgroups)
4664{
4665 /* int setgroups(size_t size, const gid_t *list); */
4666 MAYBE_PRINTF("setgroups ( %d, %p )\n", arg1, arg2);
4667 if (arg1 > 0)
4668 SYSCALL_TRACK( pre_mem_read, tid, "setgroups(list)", arg2,
4669 arg1 * sizeof(gid_t) );
4670}
4671
4672PREALIAS(setgroups32, setgroups);
4673
4674PRE(setpgid)
4675{
4676 /* int setpgid(pid_t pid, pid_t pgid); */
4677 MAYBE_PRINTF("setpgid ( %d, %d )\n", arg1, arg2);
4678}
4679
4680POST(setpgid)
4681{
4682 VG_(main_pgrp) = VG_(getpgrp)();
4683}
4684
4685PRE(setregid32)
4686{
4687 /* int setregid(gid_t rgid, gid_t egid); */
4688 MAYBE_PRINTF("setregid32(?) ( %d, %d )\n", arg1, arg2);
4689}
4690
4691PRE(setresuid32)
4692{
4693 /* int setresuid(uid_t ruid, uid_t euid, uid_t suid); */
4694 MAYBE_PRINTF("setresuid32(?) ( %d, %d, %d )\n", arg1, arg2, arg3);
4695}
4696
4697PRE(setreuid)
4698{
4699 /* int setreuid(uid_t ruid, uid_t euid); */
4700 MAYBE_PRINTF("setreuid ( 0x%x, 0x%x )\n", arg1, arg2);
4701}
4702
4703PREALIAS(setreuid32, setreuid);
4704
4705PRE(setrlimit)
4706{
4707 /* int setrlimit (int resource, const struct rlimit *rlim); */
4708 MAYBE_PRINTF("setrlimit ( %d, %p )\n", arg1,arg2);
4709 SYSCALL_TRACK( pre_mem_read, tid, "setrlimit(rlim)",
fitzhardingeb50068f2004-02-24 23:42:55 +00004710 arg2, sizeof(struct vki_rlimit) );
4711
thughesad1c9562004-06-26 11:27:52 +00004712 if (arg1 == VKI_RLIMIT_NOFILE) {
4713 if (((vki_rlimit *)arg2)->rlim_cur > VG_(fd_hard_limit) ||
4714 ((vki_rlimit *)arg2)->rlim_max != VG_(fd_hard_limit)) {
nethercote35122912004-10-18 17:00:30 +00004715 set_result( -VKI_EPERM );
thughesad1c9562004-06-26 11:27:52 +00004716 }
4717 else {
4718 VG_(fd_soft_limit) = ((vki_rlimit *)arg2)->rlim_cur;
nethercote35122912004-10-18 17:00:30 +00004719 set_result( 0 );
thughesad1c9562004-06-26 11:27:52 +00004720 }
4721 }
4722 else if (arg1 == VKI_RLIMIT_DATA) {
thughesaa4fb112004-09-11 14:19:25 +00004723 if (((vki_rlimit *)arg2)->rlim_cur > ((vki_rlimit *)arg2)->rlim_max ||
4724 ((vki_rlimit *)arg2)->rlim_max > ((vki_rlimit *)arg2)->rlim_max) {
nethercote35122912004-10-18 17:00:30 +00004725 set_result( -VKI_EPERM );
thughesaa4fb112004-09-11 14:19:25 +00004726 }
4727 else {
4728 VG_(client_rlimit_data) = *(vki_rlimit *)arg2;
nethercote35122912004-10-18 17:00:30 +00004729 set_result( 0 );
thughesaa4fb112004-09-11 14:19:25 +00004730 }
fitzhardingeb50068f2004-02-24 23:42:55 +00004731 }
thughesc37184f2004-09-11 14:16:57 +00004732 else if (arg1 == VKI_RLIMIT_STACK && tid == 1) {
4733 if (((vki_rlimit *)arg2)->rlim_cur > ((vki_rlimit *)arg2)->rlim_max ||
4734 ((vki_rlimit *)arg2)->rlim_max > ((vki_rlimit *)arg2)->rlim_max) {
nethercote35122912004-10-18 17:00:30 +00004735 set_result( -VKI_EPERM );
thughesc37184f2004-09-11 14:16:57 +00004736 }
4737 else {
4738 VG_(threads)[tid].stack_size = ((vki_rlimit *)arg2)->rlim_cur;
4739 VG_(client_rlimit_stack) = *(vki_rlimit *)arg2;
nethercote35122912004-10-18 17:00:30 +00004740 set_result( 0 );
thughesc37184f2004-09-11 14:16:57 +00004741 }
4742 }
jsgf855d93d2003-10-13 22:26:55 +00004743}
4744
4745PRE(setuid)
4746{
4747 /* int setuid(uid_t uid); */
4748 MAYBE_PRINTF("setuid ( %d )\n", arg1);
4749}
4750
4751PREALIAS(setuid32, setuid);
4752
4753PRE(socketcall)
4754{
4755 /* int socketcall(int call, unsigned long *args); */
4756 MAYBE_PRINTF("socketcall ( %d, %p )\n",arg1,arg2);
4757 switch (arg1 /* request */) {
4758
4759 case SYS_SOCKETPAIR:
4760 /* int socketpair(int d, int type, int protocol, int sv[2]); */
4761 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.socketpair(args)",
4762 arg2, 4*sizeof(Addr) );
4763 SYSCALL_TRACK( pre_mem_write, tid, "socketcall.socketpair(sv)",
4764 ((UInt*)arg2)[3], 2*sizeof(int) );
4765 break;
4766
4767 case SYS_SOCKET:
4768 /* int socket(int domain, int type, int protocol); */
4769 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.socket(args)",
4770 arg2, 3*sizeof(Addr) );
4771 break;
4772
4773 case SYS_BIND:
4774 /* int bind(int sockfd, struct sockaddr *my_addr,
4775 int addrlen); */
4776 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.bind(args)",
4777 arg2, 3*sizeof(Addr) );
4778 pre_mem_read_sockaddr( tid, "socketcall.bind(my_addr.%s)",
4779 (struct sockaddr *) (((UInt*)arg2)[1]), ((UInt*)arg2)[2]);
4780 break;
4781
4782 case SYS_LISTEN:
4783 /* int listen(int s, int backlog); */
4784 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.listen(args)",
4785 arg2, 2*sizeof(Addr) );
4786 break;
4787
4788 case SYS_ACCEPT: {
4789 /* int accept(int s, struct sockaddr *addr, int *addrlen); */
4790 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.accept(args)",
4791 arg2, 3*sizeof(Addr) );
4792 {
4793 Addr addr_p = ((UInt*)arg2)[1];
4794 Addr addrlen_p = ((UInt*)arg2)[2];
4795 if (addr_p != (Addr)NULL)
4796 buf_and_len_pre_check ( tid, addr_p, addrlen_p,
4797 "socketcall.accept(addr)",
4798 "socketcall.accept(addrlen_in)" );
4799 }
4800 break;
4801 }
4802
4803 case SYS_SENDTO:
4804 /* int sendto(int s, const void *msg, int len,
4805 unsigned int flags,
4806 const struct sockaddr *to, int tolen); */
4807 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.sendto(args)", arg2,
4808 6*sizeof(Addr) );
4809 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.sendto(msg)",
4810 ((UInt*)arg2)[1], /* msg */
4811 ((UInt*)arg2)[2] /* len */ );
4812 pre_mem_read_sockaddr( tid, "socketcall.sendto(to.%s)",
4813 (struct sockaddr *) (((UInt*)arg2)[4]), ((UInt*)arg2)[5]);
4814 break;
4815
4816 case SYS_SEND:
4817 /* int send(int s, const void *msg, size_t len, int flags); */
4818 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.send(args)", arg2,
4819 4*sizeof(Addr) );
4820 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.send(msg)",
4821 ((UInt*)arg2)[1], /* msg */
4822 ((UInt*)arg2)[2] /* len */ );
4823 break;
4824
4825 case SYS_RECVFROM:
4826 /* int recvfrom(int s, void *buf, int len, unsigned int flags,
4827 struct sockaddr *from, int *fromlen); */
4828 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.recvfrom(args)",
4829 arg2, 6*sizeof(Addr) );
4830 {
4831 Addr buf_p = ((UInt*)arg2)[1];
4832 Int len = ((UInt*)arg2)[2];
4833 Addr from_p = ((UInt*)arg2)[4];
4834 Addr fromlen_p = ((UInt*)arg2)[5];
4835
4836 SYSCALL_TRACK( pre_mem_write, tid, "socketcall.recvfrom(buf)",
4837 buf_p, len );
4838 if (from_p != (Addr)NULL)
4839 buf_and_len_pre_check ( tid, from_p, fromlen_p,
4840 "socketcall.recvfrom(from)",
4841 "socketcall.recvfrom(fromlen_in)" );
4842 }
4843 break;
4844
4845 case SYS_RECV:
4846 /* int recv(int s, void *buf, int len, unsigned int flags); */
4847 /* man 2 recv says:
4848 The recv call is normally used only on a connected socket
4849 (see connect(2)) and is identical to recvfrom with a NULL
4850 from parameter.
4851 */
4852 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.recv(args)",
4853 arg2, 4*sizeof(Addr) );
4854 SYSCALL_TRACK( pre_mem_write, tid, "socketcall.recv(buf)",
4855 ((UInt*)arg2)[1], /* buf */
4856 ((UInt*)arg2)[2] /* len */ );
4857 break;
4858
4859 case SYS_CONNECT:
4860 /* int connect(int sockfd,
4861 struct sockaddr *serv_addr, int addrlen ); */
4862 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.connect(args)",
4863 arg2, 3*sizeof(Addr) );
4864 SYSCALL_TRACK( pre_mem_read, tid,
4865 "socketcall.connect(serv_addr.sa_family)",
4866 ((UInt*)arg2)[1], /* serv_addr */
4867 sizeof (sa_family_t));
4868 pre_mem_read_sockaddr( tid,
4869 "socketcall.connect(serv_addr.%s)",
4870 (struct sockaddr *) (((UInt*)arg2)[1]), ((UInt*)arg2)[2]);
4871 break;
4872
4873 case SYS_SETSOCKOPT:
4874 /* int setsockopt(int s, int level, int optname,
4875 const void *optval, int optlen); */
4876 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.setsockopt(args)",
4877 arg2, 5*sizeof(Addr) );
4878 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.setsockopt(optval)",
4879 ((UInt*)arg2)[3], /* optval */
4880 ((UInt*)arg2)[4] /* optlen */ );
4881 break;
4882
4883 case SYS_GETSOCKOPT:
4884 /* int setsockopt(int s, int level, int optname,
4885 void *optval, socklen_t *optlen); */
4886 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.getsockopt(args)",
4887 arg2, 5*sizeof(Addr) );
4888 {
4889 Addr optval_p = ((UInt*)arg2)[3];
4890 Addr optlen_p = ((UInt*)arg2)[4];
4891 /* vg_assert(sizeof(socklen_t) == sizeof(UInt)); */
4892 if (optval_p != (Addr)NULL)
4893 buf_and_len_pre_check ( tid, optval_p, optlen_p,
4894 "socketcall.getsockopt(optval)",
4895 "socketcall.getsockopt(optlen)" );
4896 }
4897 break;
4898
4899 case SYS_GETSOCKNAME:
4900 /* int getsockname(int s, struct sockaddr* name, int* namelen) */
4901 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.getsockname(args)",
4902 arg2, 3*sizeof(Addr) );
4903 {
4904 Addr name_p = ((UInt*)arg2)[1];
4905 Addr namelen_p = ((UInt*)arg2)[2];
4906
4907 /* Nb: name_p cannot be NULL */
4908 buf_and_len_pre_check ( tid, name_p, namelen_p,
4909 "socketcall.getsockname(name)",
4910 "socketcall.getsockname(namelen_in)" );
4911 }
4912 break;
4913
4914 case SYS_GETPEERNAME:
4915 /* int getpeername(int s, struct sockaddr* name, int* namelen) */
4916 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.getpeername(args)",
4917 arg2, 3*sizeof(Addr) );
4918 {
4919 Addr name_p = ((UInt*)arg2)[1];
4920 Addr namelen_p = ((UInt*)arg2)[2];
4921
4922 /* Nb: name_p cannot be NULL */
4923 buf_and_len_pre_check ( tid, name_p, namelen_p,
4924 "socketcall.getpeername(name)",
4925 "socketcall.getpeername(namelen_in)" );
4926 }
4927 break;
4928
4929 case SYS_SHUTDOWN:
4930 /* int shutdown(int s, int how); */
4931 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.shutdown(args)",
4932 arg2, 2*sizeof(Addr) );
4933 break;
4934
4935 case SYS_SENDMSG: {
4936 /* int sendmsg(int s, const struct msghdr *msg, int flags); */
4937
4938 /* this causes warnings, and I don't get why. glibc bug?
4939 * (after all it's glibc providing the arguments array)
4940 SYSCALL_TRACK( pre_mem_read, "socketcall.sendmsg(args)",
4941 arg2, 3*sizeof(Addr) );
4942 */
4943
4944 struct msghdr *msg = (struct msghdr *)((UInt *)arg2)[ 1 ];
4945 msghdr_foreachfield ( tid, msg, pre_mem_read_sendmsg );
4946
4947 break;
4948 }
4949
4950 case SYS_RECVMSG: {
4951 /* int recvmsg(int s, struct msghdr *msg, int flags); */
4952
4953 /* this causes warnings, and I don't get why. glibc bug?
4954 * (after all it's glibc providing the arguments array)
4955 SYSCALL_TRACK( pre_mem_read, "socketcall.recvmsg(args)",
4956 arg2, 3*sizeof(Addr) );
4957 */
4958
4959 struct msghdr *msg = (struct msghdr *)((UInt *)arg2)[ 1 ];
4960 msghdr_foreachfield ( tid, msg, pre_mem_write_recvmsg );
4961
4962 break;
4963 }
4964
4965 default:
jsgf17059e02003-10-19 16:46:06 +00004966 VG_(message)(Vg_DebugMsg,"Warning: unhandled socketcall 0x%x",arg1);
nethercote35122912004-10-18 17:00:30 +00004967 set_result( -VKI_EINVAL );
jsgf17059e02003-10-19 16:46:06 +00004968 break;
jsgf855d93d2003-10-13 22:26:55 +00004969 }
4970}
4971
4972POST(socketcall)
4973{
4974 /* int socketcall(int call, unsigned long *args); */
4975 MAYBE_PRINTF("socketcall ( %d, %p )\n",arg1,arg2);
4976
4977 switch (arg1 /* request */) {
4978
nethercote493dd182004-02-24 23:57:47 +00004979 case SYS_SOCKETPAIR: {
4980 Int fd1 = ((UInt*)((UInt*)arg2)[3])[0];
4981 Int fd2 = ((UInt*)((UInt*)arg2)[3])[1];
jsgf855d93d2003-10-13 22:26:55 +00004982 VG_TRACK( post_mem_write, ((UInt*)arg2)[3], 2*sizeof(int) );
thughesad1c9562004-06-26 11:27:52 +00004983 if (!fd_allowed(fd1, "socketcall.socketpair", tid, True) ||
4984 !fd_allowed(fd2, "socketcall.socketpair", tid, True)) {
nethercote493dd182004-02-24 23:57:47 +00004985 VG_(close)(fd1);
4986 VG_(close)(fd2);
nethercote35122912004-10-18 17:00:30 +00004987 set_result( -VKI_EMFILE );
nethercote493dd182004-02-24 23:57:47 +00004988 } else {
4989 VG_TRACK( post_mem_write, ((UInt*)arg2)[3], 2*sizeof(int) );
4990 if (VG_(clo_track_fds)) {
4991 record_fd_open(tid, fd1, NULL);
4992 record_fd_open(tid, fd2, NULL);
4993 }
rjwalshf5f536f2003-11-17 17:45:00 +00004994 }
jsgf855d93d2003-10-13 22:26:55 +00004995 break;
nethercote493dd182004-02-24 23:57:47 +00004996 }
jsgf855d93d2003-10-13 22:26:55 +00004997
4998 case SYS_SOCKET:
thughesad1c9562004-06-26 11:27:52 +00004999 if (!fd_allowed(res, "socket", tid, True)) {
jsgf855d93d2003-10-13 22:26:55 +00005000 VG_(close)(res);
nethercote35122912004-10-18 17:00:30 +00005001 set_result( -VKI_EMFILE );
rjwalshf5f536f2003-11-17 17:45:00 +00005002 } else {
nethercote493dd182004-02-24 23:57:47 +00005003 if (VG_(clo_track_fds))
rjwalshf5f536f2003-11-17 17:45:00 +00005004 record_fd_open(tid, res, NULL);
jsgf855d93d2003-10-13 22:26:55 +00005005 }
5006 break;
5007
5008 case SYS_BIND:
5009 /* int bind(int sockfd, struct sockaddr *my_addr,
5010 int addrlen); */
5011 break;
5012
5013 case SYS_LISTEN:
5014 /* int listen(int s, int backlog); */
5015 break;
5016
5017 case SYS_ACCEPT: {
5018 /* int accept(int s, struct sockaddr *addr, int *addrlen); */
thughesad1c9562004-06-26 11:27:52 +00005019 if (!fd_allowed(res, "accept", tid, True)) {
jsgf855d93d2003-10-13 22:26:55 +00005020 VG_(close)(res);
nethercote35122912004-10-18 17:00:30 +00005021 set_result( -VKI_EMFILE );
jsgf855d93d2003-10-13 22:26:55 +00005022 } else {
5023 Addr addr_p = ((UInt*)arg2)[1];
5024 Addr addrlen_p = ((UInt*)arg2)[2];
5025
5026 if (addr_p != (Addr)NULL)
5027 buf_and_len_post_check ( tid, res, addr_p, addrlen_p,
5028 "socketcall.accept(addrlen_out)" );
nethercote493dd182004-02-24 23:57:47 +00005029 if (VG_(clo_track_fds))
rjwalshf5f536f2003-11-17 17:45:00 +00005030 record_fd_open(tid, res, NULL);
jsgf855d93d2003-10-13 22:26:55 +00005031 }
5032 break;
5033 }
5034
5035 case SYS_SENDTO:
5036 break;
5037
5038 case SYS_SEND:
5039 break;
5040
5041 case SYS_RECVFROM:
5042 {
5043 Addr buf_p = ((UInt*)arg2)[1];
5044 Int len = ((UInt*)arg2)[2];
5045 Addr from_p = ((UInt*)arg2)[4];
5046 Addr fromlen_p = ((UInt*)arg2)[5];
5047
5048 if (from_p != (Addr)NULL)
5049 buf_and_len_post_check ( tid, res, from_p, fromlen_p,
5050 "socketcall.recvfrom(fromlen_out)" );
5051 VG_TRACK( post_mem_write, buf_p, len );
5052 }
5053 break;
5054
5055 case SYS_RECV:
5056 if (res >= 0
5057 && ((UInt*)arg2)[1] != (UInt)NULL) {
5058 VG_TRACK( post_mem_write, ((UInt*)arg2)[1], /* buf */
5059 ((UInt*)arg2)[2] /* len */ );
5060 }
5061 break;
5062
5063 case SYS_CONNECT:
5064 break;
5065
5066 case SYS_SETSOCKOPT:
5067 break;
5068
5069 case SYS_GETSOCKOPT:
5070 {
5071 Addr optval_p = ((UInt*)arg2)[3];
5072 Addr optlen_p = ((UInt*)arg2)[4];
5073
5074 if (optval_p != (Addr)NULL)
5075 buf_and_len_post_check ( tid, res, optval_p, optlen_p,
5076 "socketcall.getsockopt(optlen_out)" );
5077 }
5078 break;
5079
5080 case SYS_GETSOCKNAME:
5081 {
5082 Addr name_p = ((UInt*)arg2)[1];
5083 Addr namelen_p = ((UInt*)arg2)[2];
5084
5085 buf_and_len_post_check ( tid, res, name_p, namelen_p,
5086 "socketcall.getsockname(namelen_out)" );
5087 }
5088 break;
5089
5090 case SYS_GETPEERNAME:
5091 {
5092 Addr name_p = ((UInt*)arg2)[1];
5093 Addr namelen_p = ((UInt*)arg2)[2];
5094
5095 buf_and_len_post_check ( tid, res, name_p, namelen_p,
5096 "socketcall.getpeername(namelen_out)" );
5097 }
5098 break;
5099
5100 case SYS_SHUTDOWN:
5101 break;
5102
5103 case SYS_SENDMSG:
5104 break;
5105
5106 case SYS_RECVMSG:
5107 {
5108 struct msghdr *msg = (struct msghdr *)((UInt *)arg2)[ 1 ];
5109
5110 msghdr_foreachfield( tid, msg, post_mem_write_recvmsg );
rjwalshf5f536f2003-11-17 17:45:00 +00005111 check_cmsg_for_fds( tid, msg );
jsgf855d93d2003-10-13 22:26:55 +00005112
5113 break;
5114 }
5115
5116 default:
5117 VG_(message)(Vg_DebugMsg,"FATAL: unhandled socketcall 0x%x",arg1);
5118 VG_(core_panic)("... bye!\n");
5119 break; /*NOTREACHED*/
5120 }
5121}
5122
5123PRE(stat)
5124{
5125 /* int stat(const char *file_name, struct stat *buf); */
5126 MAYBE_PRINTF("stat ( %p, %p )\n",arg1,arg2);
5127 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "stat(file_name)", arg1 );
5128 SYSCALL_TRACK( pre_mem_write, tid, "stat(buf)",
5129 arg2, sizeof(struct stat) );
5130}
5131
5132POST(stat)
5133{
5134 VG_TRACK( post_mem_write, arg2, sizeof(struct stat) );
5135}
5136
5137PRE(statfs)
5138{
5139 /* int statfs(const char *path, struct statfs *buf); */
5140 MAYBE_PRINTF("statfs ( %p, %p )\n",arg1,arg2);
5141 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "statfs(path)", arg1 );
muellerd3502b62003-11-19 00:43:57 +00005142 SYSCALL_TRACK( pre_mem_write, tid, "statfs(buf)",
thughes66d80092004-06-19 12:41:05 +00005143 arg2, sizeof(struct vki_statfs) );
muellerd3502b62003-11-19 00:43:57 +00005144}
5145
mueller44cbaeb2003-11-19 08:56:44 +00005146POST(statfs)
5147{
thughes66d80092004-06-19 12:41:05 +00005148 VG_TRACK( post_mem_write, arg2, sizeof(struct vki_statfs) );
mueller44cbaeb2003-11-19 08:56:44 +00005149}
5150
muellerd3502b62003-11-19 00:43:57 +00005151PRE(statfs64)
5152{
thughesa996d3b2004-09-24 22:57:17 +00005153 /* int statfs64(const char *path, size_t sz, struct statfs64 *buf); */
muellerd3502b62003-11-19 00:43:57 +00005154 MAYBE_PRINTF("statfs64 ( %p, %p )\n",arg1,arg2);
5155 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "statfs64(path)", arg1 );
thughesa996d3b2004-09-24 22:57:17 +00005156 SYSCALL_TRACK( pre_mem_write, tid, "statfs64(buf)", arg3, arg2 );
jsgf855d93d2003-10-13 22:26:55 +00005157}
5158
muellerd3502b62003-11-19 00:43:57 +00005159POST(statfs64)
5160{
thughesa996d3b2004-09-24 22:57:17 +00005161 VG_TRACK( post_mem_write, arg3, arg2 );
muellerd3502b62003-11-19 00:43:57 +00005162}
5163
jsgf855d93d2003-10-13 22:26:55 +00005164PRE(symlink)
5165{
5166 /* int symlink(const char *oldpath, const char *newpath); */
5167 MAYBE_PRINTF("symlink ( %p, %p )\n",arg1,arg2);
5168 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "symlink(oldpath)", arg1 );
5169 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "symlink(newpath)", arg2 );
5170}
5171
5172PRE(stat64)
5173{
5174 /* int stat64(const char *file_name, struct stat64 *buf); */
5175 MAYBE_PRINTF("stat64 ( %p, %p )\n",arg1,arg2);
5176 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "stat64(file_name)", arg1 );
5177 SYSCALL_TRACK( pre_mem_write, tid, "stat64(buf)",
5178 arg2, sizeof(struct stat64) );
5179}
5180
5181POST(stat64)
5182{
5183 VG_TRACK( post_mem_write, arg2, sizeof(struct stat64) );
5184}
5185
5186PRE(fstat64)
5187{
5188 /* int fstat64(int filedes, struct stat64 *buf); */
5189 MAYBE_PRINTF("fstat64 ( %d, %p )\n",arg1,arg2);
5190 SYSCALL_TRACK( pre_mem_write, tid, "fstat64(buf)",
5191 arg2, sizeof(struct stat64) );
5192}
5193
5194POST(fstat64)
5195{
5196 VG_TRACK( post_mem_write, arg2, sizeof(struct stat64) );
5197}
5198
5199PRE(sysinfo)
5200{
5201 /* int sysinfo(struct sysinfo *info); */
5202 MAYBE_PRINTF("sysinfo ( %p )\n",arg1);
5203 SYSCALL_TRACK( pre_mem_write, tid, "sysinfo(info)",
5204 arg1, sizeof(struct sysinfo) );
5205}
5206
5207POST(sysinfo)
5208{
5209 VG_TRACK( post_mem_write, arg1, sizeof(struct sysinfo) );
5210}
5211
5212PRE(time)
5213{
5214 /* time_t time(time_t *t); */
5215 MAYBE_PRINTF("time ( %p )\n",arg1);
5216 if (arg1 != (UInt)NULL) {
5217 SYSCALL_TRACK( pre_mem_write, tid, "time", arg1, sizeof(time_t) );
5218 }
5219}
5220
5221POST(time)
5222{
5223 if (arg1 != (UInt)NULL) {
5224 VG_TRACK( post_mem_write, arg1, sizeof(time_t) );
5225 }
5226}
5227
5228PRE(times)
5229{
5230 /* clock_t times(struct tms *buf); */
5231 MAYBE_PRINTF("times ( %p )\n",arg1);
5232 SYSCALL_TRACK( pre_mem_write, tid, "times(buf)",
5233 arg1, sizeof(struct tms) );
5234}
5235
5236POST(times)
5237{
5238 if (arg1 != (UInt)NULL) {
5239 VG_TRACK( post_mem_write, arg1, sizeof(struct tms) );
5240 }
5241}
5242
5243PRE(truncate)
5244{
nethercotee70bd7d2004-08-18 14:37:17 +00005245 /* int truncate(const char *path, off_t length); */
5246 MAYBE_PRINTF("truncate ( %p(%s), %d )\n", arg1,arg1,arg2);
jsgf855d93d2003-10-13 22:26:55 +00005247 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "truncate(path)", arg1 );
5248}
5249
5250PRE(umask)
5251{
5252 /* mode_t umask(mode_t mask); */
5253 MAYBE_PRINTF("umask ( %d )\n", arg1);
5254}
5255
5256PRE(unlink)
5257{
5258 /* int unlink(const char *pathname) */
nethercotee70bd7d2004-08-18 14:37:17 +00005259 MAYBE_PRINTF("unlink ( %p(%s) )\n",arg1, arg1);
jsgf855d93d2003-10-13 22:26:55 +00005260 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "unlink(pathname)", arg1 );
5261}
5262
5263PRE(uname)
5264{
5265 /* int uname(struct utsname *buf); */
5266 MAYBE_PRINTF("uname ( %p )\n",arg1);
5267 SYSCALL_TRACK( pre_mem_write, tid, "uname(buf)",
5268 arg1, sizeof(struct utsname) );
5269}
5270
5271POST(uname)
5272{
5273 if (arg1 != (UInt)NULL) {
5274 VG_TRACK( post_mem_write, arg1, sizeof(struct utsname) );
5275 }
5276}
5277
5278PRE(utime)
5279{
5280 /* int utime(const char *filename, struct utimbuf *buf); */
5281 MAYBE_PRINTF("utime ( %p, %p )\n", arg1,arg2);
5282 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "utime(filename)", arg1 );
5283 if (arg2 != (UInt)NULL)
5284 SYSCALL_TRACK( pre_mem_read, tid, "utime(buf)", arg2,
5285 sizeof(struct utimbuf) );
5286}
5287
5288PRE(waitpid)
5289{
5290 /* pid_t waitpid(pid_t pid, int *status, int options); */
5291
5292 MAYBE_PRINTF("waitpid ( %d, %p, %d )\n",
5293 arg1,arg2,arg3);
5294 if (arg2 != (Addr)NULL)
5295 SYSCALL_TRACK( pre_mem_write, tid, "waitpid(status)",
5296 arg2, sizeof(int) );
5297}
5298
5299POST(waitpid)
5300{
5301 if (arg2 != (Addr)NULL)
5302 VG_TRACK( post_mem_write, arg2, sizeof(int) );
5303}
5304
5305PRE(wait4)
5306{
5307 /* pid_t wait4(pid_t pid, int *status, int options,
5308 struct rusage *rusage) */
5309 MAYBE_PRINTF("wait4 ( %d, %p, %d, %p )\n",
5310 arg1,arg2,arg3,arg4);
5311 arg3 &= ~(VKI__WCLONE | VKI__WALL);
5312
5313 if (arg2 != (Addr)NULL)
5314 SYSCALL_TRACK( pre_mem_write, tid, "wait4(status)",
5315 arg2, sizeof(int) );
5316 if (arg4 != (Addr)NULL)
5317 SYSCALL_TRACK( pre_mem_write, tid, "wait4(rusage)", arg4,
5318 sizeof(struct rusage) );
5319}
5320
5321POST(wait4)
5322{
5323 if (arg2 != (Addr)NULL)
5324 VG_TRACK( post_mem_write, arg2, sizeof(int) );
5325 if (arg4 != (Addr)NULL)
5326 VG_TRACK( post_mem_write, arg4, sizeof(struct rusage) );
5327}
5328
5329PRE(writev)
5330{
5331 /* int writev(int fd, const struct iovec * vector, size_t count); */
5332 Int i;
5333 struct iovec * vec;
5334 MAYBE_PRINTF("writev ( %d, %p, %d )\n",arg1,arg2,arg3);
thughesad1c9562004-06-26 11:27:52 +00005335 if (!fd_allowed(arg1, "writev", tid, False)) {
nethercote35122912004-10-18 17:00:30 +00005336 set_result( -VKI_EBADF );
jsgf855d93d2003-10-13 22:26:55 +00005337 } else {
5338 SYSCALL_TRACK( pre_mem_read, tid, "writev(vector)",
5339 arg2, arg3 * sizeof(struct iovec) );
5340 /* ToDo: don't do any of the following if the vector is invalid */
5341 vec = (struct iovec *)arg2;
5342 for (i = 0; i < (Int)arg3; i++)
5343 SYSCALL_TRACK( pre_mem_read, tid, "writev(vector[...])",
nethercotea8c1e922004-10-26 10:57:24 +00005344 (Addr)vec[i].iov_base, vec[i].iov_len );
jsgf855d93d2003-10-13 22:26:55 +00005345 }
5346}
5347
5348PRE(prctl)
5349{
5350 /* int prctl(int option, unsigned long arg2, unsigned long arg3,
5351 unsigned long arg4, unsigned long arg5); */
5352 MAYBE_PRINTF( "prctl ( %d, %d, %d, %d, %d )\n", arg1, arg2, arg3,
5353 arg4, arg5 );
5354}
5355
5356PRE(adjtimex)
5357{
5358 struct timex *tx = (struct timex *)arg1;
5359 MAYBE_PRINTF("adjtimex ( %p )\n", arg1);
5360
5361 SYSCALL_TRACK(pre_mem_read, tid, "adjtimex(timex->modes)", arg1, sizeof(tx->modes));
5362
5363#define ADJX(bit,field) \
5364 if (tx->modes & bit) \
5365 SYSCALL_TRACK(pre_mem_read, tid, \
5366 "adjtimex(timex->"#field")", \
nethercotea8c1e922004-10-26 10:57:24 +00005367 (Addr)&tx->field, sizeof(tx->field))
jsgf855d93d2003-10-13 22:26:55 +00005368 ADJX(ADJ_FREQUENCY, freq);
5369 ADJX(ADJ_MAXERROR, maxerror);
5370 ADJX(ADJ_ESTERROR, esterror);
5371 ADJX(ADJ_STATUS, status);
5372 ADJX(ADJ_TIMECONST, constant);
5373 ADJX(ADJ_TICK, tick);
5374#undef ADJX
5375
5376 SYSCALL_TRACK(pre_mem_write, tid, "adjtimex(timex)", arg1, sizeof(struct timex));
5377}
5378
5379POST(adjtimex)
5380{
5381 VG_TRACK(post_mem_write, arg1, sizeof(struct timex));
5382}
5383
muellerd3502b62003-11-19 00:43:57 +00005384PRE(utimes)
5385{
5386 /* int utimes(const char *filename, struct timeval *tvp); */
5387 MAYBE_PRINTF("utimes ( %p, %p )\n", arg1,arg2);
5388 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "utimes(filename)", arg1 );
5389 if (arg2 != (UInt)NULL)
5390 SYSCALL_TRACK( pre_mem_read, tid, "utimes(tvp)", arg2,
5391 sizeof(struct timeval) );
5392}
5393
fitzhardinge47735af2004-01-21 01:27:27 +00005394PRE(futex)
5395{
5396 /* int futex(void *futex, int op, int val, const struct timespec *timeout); */
5397 MAYBE_PRINTF("futex ( %p, %d, %d, %p, %p )\n", arg1,arg2,arg3,arg4,arg5);
5398 SYSCALL_TRACK( pre_mem_read, tid, "futex(futex)", arg1, sizeof(int) );
5399 if (arg2 == VKI_FUTEX_WAIT && arg4 != (UInt)NULL)
5400 SYSCALL_TRACK( pre_mem_read, tid, "futex(timeout)", arg4,
5401 sizeof(struct timespec) );
5402 if (arg2 == VKI_FUTEX_REQUEUE)
5403 SYSCALL_TRACK( pre_mem_read, tid, "futex(futex2)", arg4, sizeof(int) );
5404}
5405
5406POST(futex)
5407{
nethercotefe082612004-07-10 18:08:13 +00005408 VG_TRACK( post_mem_write, arg1, sizeof(int) );
5409 if (arg2 == VKI_FUTEX_FD) {
5410 if (!fd_allowed(res, "futex", tid, True)) {
5411 VG_(close)(res);
nethercote35122912004-10-18 17:00:30 +00005412 set_result( -VKI_EMFILE );
nethercotefe082612004-07-10 18:08:13 +00005413 } else {
5414 if (VG_(clo_track_fds))
5415 record_fd_open(tid, res, VG_(arena_strdup)(VG_AR_CORE, (Char*)arg1));
nethercote493dd182004-02-24 23:57:47 +00005416 }
fitzhardinge47735af2004-01-21 01:27:27 +00005417 }
5418}
5419
thughes2f8d5f82004-09-11 14:29:19 +00005420PRE(sched_setaffinity)
5421{
5422 /* int sched_setaffinity(pid_t pid, unsigned int len, unsigned long *mask) */
5423 MAYBE_PRINTF("sched_setaffinity ( %d, %d, %p )\n", arg1, arg2, arg3);
5424 SYSCALL_TRACK(pre_mem_read, tid, "sched_setaffinity(mask)", arg3, arg2);
5425}
5426
5427PRE(sched_getaffinity)
5428{
5429 /* int sched_setaffinity(pid_t pid, unsigned int len, unsigned long *mask) */
5430 MAYBE_PRINTF("sched_getaffinity ( %d, %d, %p )\n", arg1, arg2, arg3);
5431 SYSCALL_TRACK(pre_mem_write, tid, "sched_getaffinity(mask)", arg3, arg2);
5432}
5433
5434POST(sched_getaffinity)
5435{
5436 VG_TRACK(post_mem_write, arg3, arg2);
5437}
5438
nethercote2bc5a212004-04-10 00:26:10 +00005439PRE(acct)
5440{
5441 /* int acct(const char *filename); */
5442 MAYBE_PRINTF("acct ( %p )\n", arg1);
5443 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "acct(filename)", arg1 );
5444}
5445
jsgf855d93d2003-10-13 22:26:55 +00005446#define SIGNAL_SIMULATION 1
5447
5448PRE(pause)
5449{
5450 /* int pause(void); */
5451 MAYBE_PRINTF("pause ( )\n");
5452}
5453
5454PRE(rt_sigsuspend)
5455{
5456 /* int sigsuspend(const sigset_t *mask); */
5457 MAYBE_PRINTF("sigsuspend ( %p )\n", arg1 );
5458 if (arg1 != (Addr)NULL) {
5459 /* above NULL test is paranoia */
5460 SYSCALL_TRACK( pre_mem_read, tid, "sigsuspend(mask)", arg1,
5461 sizeof(vki_ksigset_t) );
5462 }
5463}
5464
5465PREALIAS(sigsuspend, rt_sigsuspend);
5466
5467PRE(rt_sigtimedwait)
5468{
5469 /* int sigtimedwait(const sigset_t *set, siginfo_t *info,
5470 const struct timespec timeout); */
nethercote9e7e7552003-11-01 14:03:37 +00005471 MAYBE_PRINTF("sigtimedwait ( %p, %p, timeout )\n", arg1, arg2);
5472 if (arg1 != (UInt)NULL)
5473 SYSCALL_TRACK( pre_mem_read, tid, "sigtimedwait(set)", arg1,
5474 sizeof(vki_ksigset_t));
jsgf855d93d2003-10-13 22:26:55 +00005475 if (arg2 != (UInt)NULL)
5476 SYSCALL_TRACK( pre_mem_write, tid, "sigtimedwait(info)", arg2,
5477 sizeof(siginfo_t) );
5478}
5479
5480POST(rt_sigtimedwait)
5481{
5482 if (arg2 != (UInt)NULL)
5483 VG_TRACK( post_mem_write, arg2, sizeof(siginfo_t) );
5484}
5485
5486PRE(rt_sigqueueinfo)
5487{
5488 /* long sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo) */
5489 MAYBE_PRINTF("rt_sigqueueinfo(%d, %d, %p)\n", arg1, arg2, arg3);
5490 if (arg2 != (UInt)NULL)
5491 SYSCALL_TRACK( pre_mem_read, tid, "sigqueueinfo(uinfo)", arg3,
5492 sizeof(siginfo_t) );
5493}
5494
5495POST(rt_sigqueueinfo)
5496{
5497 if (res >= 0 &&
5498 arg2 != 0 &&
5499 !VG_(is_sig_ign)(arg2) &&
5500 !VG_(ksigismember)(&tst->eff_sig_mask, arg2) &&
5501 arg1 == VG_(getpid)()) {
5502 VG_(proxy_waitsig)();
5503 }
5504}
5505
5506PRE(sigaltstack)
5507{
5508 /* int sigaltstack(const stack_t *ss, stack_t *oss); */
5509 MAYBE_PRINTF("sigaltstack ( %p, %p )\n",arg1,arg2);
5510 if (arg1 != (UInt)NULL) {
5511 SYSCALL_TRACK( pre_mem_read, tid, "sigaltstack(ss)",
5512 arg1, sizeof(vki_kstack_t) );
5513 }
5514 if (arg2 != (UInt)NULL) {
5515 SYSCALL_TRACK( pre_mem_write, tid, "sigaltstack(oss)",
5516 arg2, sizeof(vki_kstack_t) );
5517 }
5518
5519 if (SIGNAL_SIMULATION)
5520 VG_(do__NR_sigaltstack) (tid);
5521}
5522
5523POST(sigaltstack)
5524{
5525 if (res == 0 && arg2 != (UInt)NULL)
5526 VG_TRACK( post_mem_write, arg2, sizeof(vki_kstack_t));
5527}
5528
5529PRE(sigaction)
5530{
5531 /* int sigaction(int signum, struct k_sigaction *act,
5532 struct k_sigaction *oldact); */
5533 MAYBE_PRINTF("sigaction ( %d, %p, %p )\n",arg1,arg2,arg3);
5534 if (arg2 != (UInt)NULL)
5535 SYSCALL_TRACK( pre_mem_read, tid, "sigaction(act)",
5536 arg2, sizeof(vki_ksigaction));
5537 if (arg3 != (UInt)NULL)
5538 SYSCALL_TRACK( pre_mem_write, tid, "sigaction(oldact)",
5539 arg3, sizeof(vki_ksigaction));
5540
5541 if (SIGNAL_SIMULATION)
5542 VG_(do__NR_sigaction)(tid);
5543}
5544
5545POST(sigaction)
5546{
5547 if (res == 0 && arg3 != (UInt)NULL)
5548 VG_TRACK( post_mem_write, arg3, sizeof(vki_ksigaction));
5549}
5550
5551PREALIAS(rt_sigaction, sigaction);
5552POSTALIAS(rt_sigaction, sigaction);
5553
5554PRE(sigprocmask)
5555{
5556 /* int sigprocmask(int how, k_sigset_t *set,
5557 k_sigset_t *oldset); */
5558 MAYBE_PRINTF("sigprocmask ( %d, %p, %p )\n",arg1,arg2,arg3);
5559 if (arg2 != (UInt)NULL)
5560 SYSCALL_TRACK( pre_mem_read, tid, "sigprocmask(set)",
5561 arg2, sizeof(vki_ksigset_t));
5562 if (arg3 != (UInt)NULL)
5563 SYSCALL_TRACK( pre_mem_write, tid, "sigprocmask(oldset)",
5564 arg3, sizeof(vki_ksigset_t));
5565
5566 if (SIGNAL_SIMULATION)
5567 VG_(do__NR_sigprocmask) ( tid,
5568 arg1 /*how*/,
5569 (vki_ksigset_t*) arg2,
5570 (vki_ksigset_t*) arg3 );
5571}
5572
5573POST(sigprocmask)
5574{
5575 if (res == 0 && arg3 != (UInt)NULL)
5576 VG_TRACK( post_mem_write, arg3, sizeof(vki_ksigset_t));
5577}
5578
5579PREALIAS(rt_sigprocmask, sigprocmask);
5580POSTALIAS(rt_sigprocmask, sigprocmask);
5581
5582PRE(sigpending)
5583{
5584 /* int sigpending( sigset_t *set ) ; */
5585 MAYBE_PRINTF( "sigpending ( %p )\n", arg1 );
5586 SYSCALL_TRACK( pre_mem_write, tid, "sigpending(set)",
5587 arg1, sizeof(vki_ksigset_t));
5588}
5589
5590POST(sigpending)
5591{
nethercotefe082612004-07-10 18:08:13 +00005592 VG_TRACK( post_mem_write, arg1, sizeof( vki_ksigset_t ) ) ;
jsgf855d93d2003-10-13 22:26:55 +00005593}
5594
5595PREALIAS(rt_sigpending, sigpending);
5596POSTALIAS(rt_sigpending, sigpending);
5597
thughes9aaebc32004-07-15 23:13:37 +00005598PRE(io_setup)
5599{
5600 UInt size;
5601 Addr addr;
5602
5603 /* long io_setup (unsigned nr_events, aio_context_t *ctxp); */
5604 MAYBE_PRINTF("io_setup ( %ul, %p )\n",arg1,arg2);
5605 SYSCALL_TRACK( pre_mem_write, tid, "io_setup(ctxp)",
5606 arg2, sizeof(vki_aio_context_t) );
5607
5608 size = PGROUNDUP(sizeof(vki_aio_ring) + arg1 * sizeof(vki_io_event));
5609 addr = VG_(find_map_space)(0, size, True);
5610 VG_(map_segment)(addr, size, VKI_PROT_READ|VKI_PROT_EXEC, SF_FIXED);
5611
5612 VG_(pad_address_space)();
nethercote35122912004-10-18 17:00:30 +00005613 set_result( VG_(do_syscall)(SYSNO, arg1, arg2) );
thughes9aaebc32004-07-15 23:13:37 +00005614 VG_(unpad_address_space)();
5615
5616 if (res == 0) {
5617 vki_aio_ring *r = *(vki_aio_ring **)arg2;
5618
5619 vg_assert(addr == (Addr)r);
5620 vg_assert(valid_client_addr(addr, size, tid, "io_setup"));
5621
5622 VG_TRACK( new_mem_mmap, addr, size, True, True, False );
5623 VG_TRACK( post_mem_write, arg2, sizeof(vki_aio_context_t) );
5624 }
5625 else {
5626 VG_(unmap_range)(addr, size);
5627 }
5628}
5629
5630PRE(io_destroy)
5631{
5632 Segment *s = VG_(find_segment)(arg1);
5633 vki_aio_ring *r = *(vki_aio_ring **)arg1;
5634 UInt size = PGROUNDUP(sizeof(vki_aio_ring) + r->nr * sizeof(vki_io_event));
5635
5636 /* long io_destroy (aio_context_t ctx); */
5637 MAYBE_PRINTF("io_destroy ( %ul )\n",arg1);
5638
nethercote35122912004-10-18 17:00:30 +00005639 set_result( VG_(do_syscall)(SYSNO, arg1) );
thughes9aaebc32004-07-15 23:13:37 +00005640
5641 if (res == 0 && s != NULL && VG_(seg_contains)(s, arg1, size)) {
5642 VG_TRACK( die_mem_munmap, arg1, size );
5643 VG_(unmap_range)(arg1, size);
5644 }
5645}
5646
5647PRE(io_getevents)
5648{
5649 /* long io_getevents (aio_context_t ctx_id, long min_nr, long nr,
5650 struct io_event *events, struct timespec *timeout); */
5651 MAYBE_PRINTF("io_getevents ( %ul, %l, %l, %p, %p )\n",arg1,arg2,arg3,arg4,arg5);
5652 if (arg3 > 0)
5653 SYSCALL_TRACK( pre_mem_write, tid, "io_getevents(events)",
5654 arg4, sizeof(vki_io_event)*arg3 );
5655 if (arg5 != (UInt)NULL)
5656 SYSCALL_TRACK( pre_mem_read, tid, "io_getevents(timeout)",
5657 arg5, sizeof(struct timespec));
5658}
5659
5660POST(io_getevents)
5661{
5662 int i;
5663
5664 if (res > 0) {
5665 VG_TRACK( post_mem_write, arg4, sizeof(vki_io_event)*res );
5666 for (i = 0; i < res; i++) {
5667 const vki_io_event *vev = ((vki_io_event *)arg4) + i;
5668 const vki_iocb *cb = (vki_iocb *)(UInt)vev->obj;
5669
5670 switch (cb->aio_lio_opcode) {
5671 case VKI_IOCB_CMD_PREAD:
5672 if (vev->result > 0)
5673 VG_TRACK( post_mem_write, cb->aio_buf, vev->result );
5674 break;
5675
5676 case VKI_IOCB_CMD_PWRITE:
5677 break;
5678
5679 default:
5680 VG_(message)(Vg_DebugMsg,"Warning: unhandled io_getevents opcode: %u\n",cb->aio_lio_opcode);
5681 break;
5682 }
5683 }
5684 }
5685}
5686
5687PRE(io_submit)
5688{
5689 int i;
5690
5691 /* long io_submit (aio_context_t ctx_id, long nr, struct iocb **iocbpp); */
5692 MAYBE_PRINTF("io_submit( %ul, %l, %p )\n",arg1,arg2,arg3);
5693 SYSCALL_TRACK( pre_mem_read, tid, "io_submit(iocbpp)",
5694 arg3, sizeof(vki_iocb *)*arg2 );
5695 for (i = 0; i < arg2; i++) {
5696 vki_iocb *cb = ((vki_iocb **)arg3)[i];
5697 SYSCALL_TRACK( pre_mem_read, tid, "io_submit(iocb)",
nethercotea8c1e922004-10-26 10:57:24 +00005698 (Addr)cb, sizeof(vki_iocb) );
thughes9aaebc32004-07-15 23:13:37 +00005699 switch (cb->aio_lio_opcode) {
5700 case VKI_IOCB_CMD_PREAD:
5701 SYSCALL_TRACK( pre_mem_write, tid, "io_submit(PREAD)",
5702 cb->aio_buf, cb->aio_nbytes );
5703 break;
5704
5705 case VKI_IOCB_CMD_PWRITE:
5706 SYSCALL_TRACK( pre_mem_read, tid, "io_submit(PWRITE)",
5707 cb->aio_buf, cb->aio_nbytes );
5708 break;
5709
5710 default:
5711 VG_(message)(Vg_DebugMsg,"Warning: unhandled io_submit opcode: %u\n",cb->aio_lio_opcode);
5712 break;
5713 }
5714 }
5715}
5716
5717PRE(io_cancel)
5718{
5719 /* long io_cancel (aio_context_t ctx_id, struct iocb *iocb,
5720 struct io_event *result); */
5721 MAYBE_PRINTF("io_cancel( %ul, %p, %p )\n",arg1,arg2,arg3);
5722 SYSCALL_TRACK( pre_mem_read, tid, "io_cancel(iocb)",
5723 arg2, sizeof(vki_iocb) );
5724 SYSCALL_TRACK( pre_mem_write, tid, "io_cancel(result)",
5725 arg3, sizeof(vki_io_event) );
5726}
5727
5728POST(io_cancel)
5729{
5730 VG_TRACK( post_mem_write, arg3, sizeof(vki_io_event) );
5731}
jsgf855d93d2003-10-13 22:26:55 +00005732
thughes8579b102004-08-14 18:52:27 +00005733PRE(mq_open)
5734{
5735 /* mqd_t mq_open(const char *name, int oflag, ...); */
5736 MAYBE_PRINTF("mq_open( %p(%s), %d )\n", arg1,arg1,arg2);
5737 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "mq_open(name)", arg1 );
5738 if ((arg2 & VKI_O_CREAT) != 0 && arg4 != 0) {
5739 const struct vki_mq_attr *attr = (struct vki_mq_attr *)arg4;
5740 SYSCALL_TRACK( pre_mem_read, tid, "mq_open(attr->mq_maxmsg)",
5741 (Addr)&attr->mq_maxmsg, sizeof(attr->mq_maxmsg) );
5742 SYSCALL_TRACK( pre_mem_read, tid, "mq_open(attr->mq_msgsize)",
5743 (Addr)&attr->mq_msgsize, sizeof(attr->mq_msgsize) );
5744 }
5745}
5746
5747POST(mq_open)
5748{
5749 if (!fd_allowed(res, "mq_open", tid, True)) {
5750 VG_(close)(res);
nethercote35122912004-10-18 17:00:30 +00005751 set_result( -VKI_EMFILE );
thughes8579b102004-08-14 18:52:27 +00005752 } else {
5753 if (VG_(clo_track_fds))
5754 record_fd_open(tid, res, VG_(arena_strdup)(VG_AR_CORE, (Char*)arg1));
5755 }
5756 MAYBE_PRINTF("%d\n",res);
5757}
5758
5759PRE(mq_unlink)
5760{
5761 /* int mq_unlink(const char *name) */
nethercotee70bd7d2004-08-18 14:37:17 +00005762 MAYBE_PRINTF("mq_unlink ( %p(%s) )\n",arg1, arg1);
thughes8579b102004-08-14 18:52:27 +00005763 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "mq_unlink(name)", arg1 );
5764}
5765
5766PRE(mq_timedsend)
5767{
5768 /* int mq_timedsend(mqd_t mqdes, const char *msg_ptr, size_t msg_len,
5769 unsigned msg_prio, const struct timespec *abs_timeout); */
5770 MAYBE_PRINTF("mq_timedsend ( %d, %p, %d, %d, %p )\n",
5771 arg1,arg2,arg3,arg4,arg5);
5772 if (!fd_allowed(arg1, "mq_timedsend", tid, False)) {
nethercote35122912004-10-18 17:00:30 +00005773 set_result( -VKI_EBADF );
thughes8579b102004-08-14 18:52:27 +00005774 } else {
5775 SYSCALL_TRACK( pre_mem_read, tid, "mq_timedsend(msg_ptr)", arg2, arg3 );
5776 if (arg5 != 0)
5777 SYSCALL_TRACK( pre_mem_read, tid, "mq_timedsend(abs_timeout)", arg5,
5778 sizeof(struct timespec) );
5779 }
5780}
5781
5782PRE(mq_timedreceive)
5783{
5784 /* ssize_t mq_timedreceive(mqd_t mqdes, char *restrict msg_ptr,
5785 size_t msg_len, unsigned *restrict msg_prio,
5786 const struct timespec *restrict abs_timeout); */
5787 MAYBE_PRINTF("mq_timedreceive( %d, %p, %d, %p, %p )\n",
5788 arg1,arg2,arg3,arg4,arg5);
5789 if (!fd_allowed(arg1, "mq_timedreceive", tid, False)) {
nethercote35122912004-10-18 17:00:30 +00005790 set_result( -VKI_EBADF );
thughes8579b102004-08-14 18:52:27 +00005791 } else {
5792 SYSCALL_TRACK( pre_mem_write, tid, "mq_timedreceive(msg_ptr)", arg2, arg3 );
5793 if (arg4 != 0)
5794 SYSCALL_TRACK( pre_mem_write, tid, "mq_timedreceive(msg_prio)",
5795 arg4, sizeof(unsigned int) );
5796 if (arg5 != 0)
5797 SYSCALL_TRACK( pre_mem_read, tid, "mq_timedreceive(abs_timeout)",
5798 arg5, sizeof(struct timespec) );
5799 }
5800}
5801
5802POST(mq_timedreceive)
5803{
5804 VG_TRACK( post_mem_write, arg2, arg3 );
5805 if (arg4 != 0)
5806 VG_TRACK( post_mem_write, arg4, sizeof(unsigned int) );
5807}
5808
5809PRE(mq_notify)
5810{
5811 /* int mq_notify(mqd_t mqdes, const struct sigevent *notification); */
5812 MAYBE_PRINTF("mq_notify( %d, %p )\n", arg1,arg2 );
5813 if (!fd_allowed(arg1, "mq_notify", tid, False))
nethercote35122912004-10-18 17:00:30 +00005814 set_result( -VKI_EBADF );
thughes8579b102004-08-14 18:52:27 +00005815 else if (arg2 != 0)
5816 SYSCALL_TRACK( pre_mem_read, tid, "mq_notify", arg2,
5817 sizeof(struct sigevent) );
5818}
5819
5820PRE(mq_getsetattr)
5821{
5822 /* int mq_getsetattr(mqd_t mqdes, const struct mq_attr *restrict mqstat,
5823 struct mq_attr *restrict omqstat); */
5824 MAYBE_PRINTF("mq_getsetattr( %d, %p, %p )\n", arg1,arg2,arg3 );
5825 if (!fd_allowed(arg1, "mq_getsetattr", tid, False)) {
nethercote35122912004-10-18 17:00:30 +00005826 set_result( -VKI_EBADF );
thughes8579b102004-08-14 18:52:27 +00005827 } else {
5828 if (arg2 != 0) {
5829 const struct vki_mq_attr *attr = (struct vki_mq_attr *)arg2;
5830 SYSCALL_TRACK( pre_mem_read, tid, "mq_getsetattr(mqstat->mq_flags)",
5831 (Addr)&attr->mq_flags, sizeof(attr->mq_flags) );
5832 }
5833 if (arg3 != 0)
5834 SYSCALL_TRACK( pre_mem_write, tid, "mq_getsetattr(omqstat)", arg3,
5835 sizeof(struct vki_mq_attr) );
5836 }
5837}
5838
5839POST(mq_getsetattr)
5840{
5841 if (arg3 != 0)
5842 VG_TRACK( post_mem_write, arg3, sizeof(struct vki_mq_attr) );
5843}
5844
thughese1a925d2004-08-30 19:50:02 +00005845PRE(timer_create)
5846{
5847 /* int timer_create(clockid_t clock_id, struct sigevent *restrict evp,
5848 timer_t *restrict timerid); */
5849 MAYBE_PRINTF("timer_create( %d, %p, %p )\n", arg1,arg2,arg3);
5850 if (arg2 != 0)
5851 SYSCALL_TRACK( pre_mem_read, tid, "timer_create(evp)", arg2,
5852 sizeof(struct sigevent) );
5853 SYSCALL_TRACK( pre_mem_write, tid, "timer_create(timerid)", arg3,
5854 sizeof(timer_t) );
5855}
5856
5857POST(timer_create)
5858{
5859 VG_TRACK( post_mem_write, arg3, sizeof(timer_t) );
5860}
5861
5862PRE(timer_settime)
5863{
5864 /* int timer_settime(timer_t timerid, int flags,
5865 const struct itimerspec *restrict value,
5866 struct itimerspec *restrict ovalue); */
5867 MAYBE_PRINTF("timer_settime( %p, %d, %p, %p )\n", arg1,arg2,arg3,arg4);
5868 SYSCALL_TRACK( pre_mem_read, tid, "timer_settime(value)", arg3,
5869 sizeof(struct vki_itimerspec) );
5870 if (arg4 != 0)
5871 SYSCALL_TRACK( pre_mem_write, tid, "timer_settime(ovalue)", arg4,
5872 sizeof(struct vki_itimerspec) );
5873}
5874
5875POST(timer_settime)
5876{
5877 if (arg4 != 0)
5878 VG_TRACK( post_mem_write, arg4, sizeof(struct vki_itimerspec) );
5879}
5880
5881PRE(timer_gettime)
5882{
5883 /* int timer_gettime(timer_t timerid, struct itimerspec *value); */
5884 MAYBE_PRINTF("timer_gettime( %p, %p )\n", arg1,arg2);
5885 SYSCALL_TRACK( pre_mem_write, tid, "timer_gettime(value)", arg2,
5886 sizeof(struct vki_itimerspec));
5887}
5888
5889POST(timer_gettime)
5890{
5891 VG_TRACK( post_mem_write, arg2, sizeof(struct vki_itimerspec) );
5892}
5893
5894PRE(timer_getoverrun)
5895{
5896 /* int timer_getoverrun(timer_t timerid); */
5897 MAYBE_PRINTF("timer_getoverrun( %p )\n", arg1);
5898}
5899
5900PRE(timer_delete)
5901{
5902 /* int timer_delete(timer_t timerid); */
5903 MAYBE_PRINTF("timer_delete( %p )\n", arg1);
5904}
5905
5906PRE(clock_settime)
5907{
5908 /* int clock_settime(clockid_t clk_id, const struct timespec *tp); */
5909 MAYBE_PRINTF("clock_settime( %d, %p )\n", arg1,arg2);
5910 SYSCALL_TRACK(pre_mem_read, tid, "clock_gettime(tp)",
5911 arg2, sizeof(struct timespec) );
5912}
5913
5914PRE(clock_gettime)
5915{
5916 /* int clock_gettime(clockid_t clk_id, struct timespec *tp); */
5917 MAYBE_PRINTF("clock_gettime( %d, %p )\n" , arg1,arg2);
5918 SYSCALL_TRACK(pre_mem_write, tid, "clock_gettime(tp)",
5919 arg2, sizeof(struct timespec) );
5920}
5921
5922POST(clock_gettime)
5923{
5924 VG_TRACK( post_mem_write, arg2, sizeof(struct timespec) );
5925}
5926
5927PRE(clock_getres)
5928{
5929 /* int clock_getres(clockid_t clk_id, struct timespec *res); */
5930 MAYBE_PRINTF("clock_getres( %d, %p )\n" , arg1,arg2);
5931 SYSCALL_TRACK(pre_mem_write, tid, "clock_getres(res)",
5932 arg2, sizeof(struct timespec) );
5933}
5934
5935POST(clock_getres)
5936{
5937 VG_TRACK( post_mem_write, arg2, sizeof(struct timespec) );
5938}
5939
jsgf855d93d2003-10-13 22:26:55 +00005940struct sys_info {
thughesbaa46e52004-07-29 17:44:23 +00005941 UInt flags;
jsgf855d93d2003-10-13 22:26:55 +00005942 void (*before)(ThreadId tid, ThreadState *tst);
5943 void (*after)(ThreadId tid, ThreadState *tst);
5944};
thughesbaa46e52004-07-29 17:44:23 +00005945#define SYSB_(name, flags) [__NR_##name] = { flags, before_##name, NULL }
5946#define SYSBA(name, flags) [__NR_##name] = { flags, before_##name, after_##name }
jsgf855d93d2003-10-13 22:26:55 +00005947
5948static void bad_before(ThreadId tid, ThreadState *tst)
5949{
5950 VG_(message)
nethercote427e9512004-08-23 16:36:09 +00005951 (Vg_DebugMsg,"WARNING: unhandled syscall: %d", SYSNO);
fitzhardinge98abfc72003-12-16 02:05:15 +00005952 if (VG_(clo_verbosity) > 1) {
5953 ExeContext *ec = VG_(get_ExeContext)(tid);
5954 VG_(pp_ExeContext)(ec);
5955 }
jsgf855d93d2003-10-13 22:26:55 +00005956 VG_(message)
5957 (Vg_DebugMsg,"Do not panic. You may be able to fix this easily.");
5958 VG_(message)
5959 (Vg_DebugMsg,"Read the file README_MISSING_SYSCALL_OR_IOCTL.");
5960
nethercote35122912004-10-18 17:00:30 +00005961 set_result( -VKI_ENOSYS );
jsgf855d93d2003-10-13 22:26:55 +00005962}
5963
5964static void bad_after(ThreadId tid, ThreadState *tst)
5965{
5966}
5967
5968static const struct sys_info bad_sys = { False, bad_before, bad_after };
5969
5970static const struct sys_info special_sys[] = {
5971 /* special */
thughesbaa46e52004-07-29 17:44:23 +00005972 SYSB_(exit_group, 0),
5973 SYSB_(exit, 0),
5974 SYSB_(clone, 0),
jsgf855d93d2003-10-13 22:26:55 +00005975
thughesbaa46e52004-07-29 17:44:23 +00005976 SYSB_(modify_ldt, 0),
5977 SYSB_(set_thread_area, 0),
5978 SYSB_(get_thread_area, 0),
5979 SYSB_(set_tid_address, 0),
jsgf855d93d2003-10-13 22:26:55 +00005980
thughesbaa46e52004-07-29 17:44:23 +00005981 SYSB_(execve, 0),
5982 SYSB_(brk, 0),
5983 SYSB_(mmap, 0),
5984 SYSB_(mremap, 0),
fitzhardingee1c06d82003-10-30 07:21:44 +00005985
thughesbaa46e52004-07-29 17:44:23 +00005986 SYSB_(io_setup, 0),
5987 SYSB_(io_destroy, 0),
thughes9aaebc32004-07-15 23:13:37 +00005988
jsgf855d93d2003-10-13 22:26:55 +00005989#if SIGNAL_SIMULATION
thughesbaa46e52004-07-29 17:44:23 +00005990 SYSBA(sigaltstack, 0),
5991 SYSBA(rt_sigaction, 0),
5992 SYSBA(sigaction, 0),
5993 SYSBA(rt_sigprocmask, 0),
5994 SYSBA(sigprocmask, 0),
jsgf855d93d2003-10-13 22:26:55 +00005995#endif /* SIGNAL_SIMULATION */
5996};
5997#define MAX_SPECIAL_SYS (sizeof(special_sys)/sizeof(special_sys[0]))
5998
5999static const struct sys_info sys_info[] = {
thughesbaa46e52004-07-29 17:44:23 +00006000 SYSBA(ptrace, 0),
6001 SYSB_(mount, MayBlock),
6002 SYSB_(umount, 0),
jsgf855d93d2003-10-13 22:26:55 +00006003
thughesbaa46e52004-07-29 17:44:23 +00006004 SYSB_(setresgid, 0),
6005 SYSB_(vhangup, 0),
6006 SYSB_(iopl, 0),
jsgf855d93d2003-10-13 22:26:55 +00006007
thughesbaa46e52004-07-29 17:44:23 +00006008 SYSB_(setxattr, MayBlock),
6009 SYSB_(lsetxattr, MayBlock),
6010 SYSB_(fsetxattr, MayBlock),
6011 SYSBA(getxattr, MayBlock),
6012 SYSBA(lgetxattr, MayBlock),
6013 SYSBA(fgetxattr, MayBlock),
6014 SYSBA(listxattr, MayBlock),
6015 SYSBA(llistxattr, MayBlock),
6016 SYSBA(flistxattr, MayBlock),
6017 SYSB_(removexattr, MayBlock),
6018 SYSB_(lremovexattr, MayBlock),
6019 SYSB_(fremovexattr, MayBlock),
jsgf855d93d2003-10-13 22:26:55 +00006020
thughesbaa46e52004-07-29 17:44:23 +00006021 SYSB_(quotactl, 0),
6022 SYSBA(lookup_dcookie, 0),
jsgf855d93d2003-10-13 22:26:55 +00006023
thughesbaa46e52004-07-29 17:44:23 +00006024 SYSB_(truncate64, MayBlock),
6025 SYSB_(fdatasync, MayBlock),
6026 SYSB_(msync, MayBlock),
jsgf855d93d2003-10-13 22:26:55 +00006027
thughesbaa46e52004-07-29 17:44:23 +00006028 SYSBA(getpmsg, MayBlock),
6029 SYSB_(putpmsg, MayBlock),
jsgf855d93d2003-10-13 22:26:55 +00006030
thughesbaa46e52004-07-29 17:44:23 +00006031 SYSBA(syslog, MayBlock),
6032 SYSB_(personality, 0),
6033 SYSB_(chroot, 0),
6034 SYSB_(madvise, MayBlock),
6035 SYSB_(nice, 0),
6036 SYSB_(setresgid32, 0),
6037 SYSB_(setfsuid32, 0),
6038 SYSBA(_sysctl, 0),
jsgf855d93d2003-10-13 22:26:55 +00006039
thughesbaa46e52004-07-29 17:44:23 +00006040 SYSB_(sched_getscheduler, 0), /* ??? */
6041 SYSB_(sched_setscheduler, 0), /* ??? */
jsgf855d93d2003-10-13 22:26:55 +00006042
thughesbaa46e52004-07-29 17:44:23 +00006043 SYSB_(mlock, MayBlock),
6044 SYSB_(munlock, MayBlock),
6045 SYSB_(mlockall, MayBlock),
6046 SYSB_(munlockall, MayBlock),
jsgf855d93d2003-10-13 22:26:55 +00006047
thughesbaa46e52004-07-29 17:44:23 +00006048 SYSB_(sched_get_priority_max, 0), /* ??? */
6049 SYSB_(sched_get_priority_min, 0), /* ??? */
jsgf855d93d2003-10-13 22:26:55 +00006050
thughesbaa46e52004-07-29 17:44:23 +00006051 SYSB_(setpriority, 0),
6052 SYSB_(getpriority, 0),
jsgf855d93d2003-10-13 22:26:55 +00006053
thughesbaa46e52004-07-29 17:44:23 +00006054 SYSB_(setfsgid, 0),
6055 SYSB_(setregid, 0),
6056 SYSB_(setresuid, 0),
6057 SYSB_(setfsuid, 0),
jsgf855d93d2003-10-13 22:26:55 +00006058
thughesbaa46e52004-07-29 17:44:23 +00006059 SYSBA(sendfile, MayBlock),
6060 SYSBA(sendfile64, MayBlock),
6061 SYSB_(pwrite64, MayBlock),
6062 SYSB_(sync, MayBlock),
6063 SYSBA(fstatfs, 0),
thughesa996d3b2004-09-24 22:57:17 +00006064 SYSBA(fstatfs64, 0),
thughesbaa46e52004-07-29 17:44:23 +00006065 SYSB_(getsid, 0),
6066 SYSBA(pread64, MayBlock),
6067 SYSB_(mknod, 0),
6068 SYSB_(flock, MayBlock),
6069 SYSB_(init_module, MayBlock),
6070 SYSB_(ioperm, 0),
6071 SYSBA(capget, 0),
6072 SYSB_(capset, 0),
6073 SYSB_(access, 0),
6074 SYSB_(chdir, 0),
6075 SYSB_(chmod, 0),
6076 SYSB_(chown32, 0),
6077 SYSB_(lchown32, 0),
6078 SYSB_(chown, 0),
6079 SYSBA(close, 0),
6080 SYSBA(dup, 0),
6081 SYSBA(dup2, 0),
thughesd4b51a62004-07-29 21:20:11 +00006082 SYSBA(fcntl, 0),
thughesbaa46e52004-07-29 17:44:23 +00006083 SYSB_(fchdir, 0),
6084 SYSB_(fchown32, 0),
6085 SYSB_(fchown, 0),
6086 SYSB_(fchmod, 0),
thughesd4b51a62004-07-29 21:20:11 +00006087 SYSBA(fcntl64, 0),
thughesbaa46e52004-07-29 17:44:23 +00006088 SYSBA(fstat, 0),
6089 SYSBA(fork, 0),
6090 SYSB_(fsync, MayBlock),
6091 SYSB_(ftruncate, MayBlock),
6092 SYSB_(ftruncate64, MayBlock),
6093 SYSBA(getdents, MayBlock),
6094 SYSBA(getdents64, MayBlock),
nethercotefb0ccb92004-08-17 13:26:52 +00006095 SYSBA(getgroups32, 0),
thughesbaa46e52004-07-29 17:44:23 +00006096 SYSBA(getgroups, 0),
6097 SYSBA(getcwd, 0),
6098 SYSB_(geteuid, 0),
6099 SYSB_(geteuid32, 0),
6100 SYSB_(getegid, 0),
6101 SYSB_(getegid32, 0),
6102 SYSB_(getgid, 0),
6103 SYSB_(getgid32, 0),
6104 SYSB_(getpid, 0),
6105 SYSB_(getpgid, 0),
6106 SYSB_(getpgrp, 0),
6107 SYSB_(getppid, 0),
6108 SYSBA(getresgid, 0),
6109 SYSBA(getresgid32, 0),
6110 SYSBA(getresuid, 0),
6111 SYSBA(getresuid32, 0),
6112 SYSBA(ugetrlimit, 0),
6113 SYSBA(getrlimit, 0),
6114 SYSBA(getrusage, 0),
6115 SYSBA(gettimeofday, 0),
6116 SYSB_(getuid, 0),
6117 SYSB_(getuid32, 0),
thughes024f25d2004-07-29 22:40:07 +00006118 SYSBA(ipc, 0),
thughesbaa46e52004-07-29 17:44:23 +00006119 SYSBA(ioctl, MayBlock),
6120 SYSBA(kill, 0),
6121 SYSB_(link, MayBlock),
6122 SYSB_(lseek, 0),
6123 SYSBA(_llseek, 0),
6124 SYSBA(lstat, 0),
6125 SYSBA(lstat64, 0),
6126 SYSB_(mkdir, MayBlock),
6127 SYSBA(mprotect, 0),
6128 SYSBA(munmap, 0),
6129 SYSBA(mincore, 0),
6130 SYSBA(nanosleep, MayBlock|PostOnFail),
6131 SYSB_(_newselect, MayBlock),
6132 SYSBA(open, MayBlock),
6133 SYSBA(read, MayBlock),
6134 SYSB_(write, MayBlock),
6135 SYSBA(creat, MayBlock),
6136 SYSBA(pipe, 0),
6137 SYSBA(poll, MayBlock),
6138 SYSBA(epoll_create, 0),
6139 SYSB_(epoll_ctl, 0),
6140 SYSBA(epoll_wait, MayBlock),
6141 SYSBA(readlink, 0),
6142 SYSBA(readv, MayBlock),
6143 SYSB_(rename, 0),
6144 SYSB_(rmdir, MayBlock),
6145 SYSBA(sched_setparam, 0), /* ??? */
6146 SYSBA(sched_getparam, 0), /* ??? */
6147 SYSB_(sched_yield, 0), /* ??? */
6148 SYSB_(select, MayBlock),
6149 SYSB_(setfsgid32, 0),
6150 SYSB_(setgid32, 0),
6151 SYSB_(setgid, 0),
6152 SYSB_(setsid, 0),
6153 SYSB_(setgroups32, 0),
6154 SYSB_(setgroups, 0),
6155 SYSBA(setpgid, 0),
6156 SYSB_(setregid32, 0),
6157 SYSB_(setresuid32, 0),
6158 SYSB_(setreuid32, 0),
6159 SYSB_(setreuid, 0),
6160 SYSB_(setrlimit, 0),
6161 SYSB_(setuid32, 0),
6162 SYSB_(setuid, 0),
6163 SYSBA(socketcall, MayBlock),
6164 SYSBA(stat, 0),
6165 SYSBA(statfs, 0),
6166 SYSBA(statfs64, 0),
6167 SYSB_(symlink, MayBlock),
6168 SYSBA(stat64, 0),
6169 SYSBA(fstat64, 0),
6170 SYSBA(sysinfo, 0),
6171 SYSBA(time, 0),
6172 SYSBA(times, 0),
6173 SYSB_(truncate, MayBlock),
6174 SYSB_(umask, 0),
6175 SYSB_(unlink, MayBlock),
6176 SYSBA(uname, 0),
6177 SYSB_(utime, MayBlock),
6178 SYSB_(utimes, 0),
6179 SYSBA(waitpid, MayBlock),
6180 SYSBA(wait4, MayBlock),
6181 SYSB_(writev, MayBlock),
6182 SYSB_(prctl, MayBlock),
6183 SYSBA(adjtimex, 0),
6184 SYSBA(mmap2, 0),
thughesbaa46e52004-07-29 17:44:23 +00006185 SYSBA(futex, MayBlock),
thughes2f8d5f82004-09-11 14:29:19 +00006186 SYSB_(sched_setaffinity, 0),
6187 SYSBA(sched_getaffinity, 0),
thughesbaa46e52004-07-29 17:44:23 +00006188 SYSB_(acct, 0),
jsgf855d93d2003-10-13 22:26:55 +00006189
6190 /* new signal handling makes these normal blocking syscalls */
thughesbaa46e52004-07-29 17:44:23 +00006191 SYSB_(pause, MayBlock),
6192 SYSB_(sigsuspend, MayBlock),
6193 SYSB_(rt_sigsuspend, MayBlock),
6194 SYSBA(rt_sigtimedwait, MayBlock),
6195 SYSBA(rt_sigqueueinfo, 0),
fitzhardingea09a1b52003-11-07 23:09:48 +00006196
thughesbaa46e52004-07-29 17:44:23 +00006197 SYSBA(sigpending, MayBlock), /* not blocking, but must run in LWP context */
6198 SYSBA(rt_sigpending, MayBlock), /* not blocking, but must run in LWP context */
6199 SYSB_(alarm, MayBlock), /* not blocking, but must run in LWP context */
6200 SYSBA(setitimer, MayBlock), /* not blocking, but must run in LWP context */
6201 SYSBA(getitimer, MayBlock), /* not blocking, but must run in LWP context */
jsgf855d93d2003-10-13 22:26:55 +00006202
thughesbaa46e52004-07-29 17:44:23 +00006203 SYSBA(io_getevents, MayBlock),
6204 SYSB_(io_submit, 0),
6205 SYSBA(io_cancel, 0),
thughes9aaebc32004-07-15 23:13:37 +00006206
thughes8579b102004-08-14 18:52:27 +00006207 SYSBA(mq_open, 0),
6208 SYSB_(mq_unlink, 0),
6209 SYSB_(mq_timedsend, MayBlock),
6210 SYSBA(mq_timedreceive, MayBlock),
6211 SYSB_(mq_notify, 0),
6212 SYSBA(mq_getsetattr, 0),
6213
thughese1a925d2004-08-30 19:50:02 +00006214 SYSBA(timer_create, 0),
6215 SYSBA(timer_settime, 0),
6216 SYSBA(timer_gettime, 0),
6217 SYSB_(timer_getoverrun, 0),
6218 SYSB_(timer_delete, 0),
6219
6220 SYSB_(clock_settime, 0),
6221 SYSBA(clock_gettime, 0),
6222 SYSBA(clock_getres, 0),
6223
jsgf855d93d2003-10-13 22:26:55 +00006224#if !SIGNAL_SIMULATION
thughesbaa46e52004-07-29 17:44:23 +00006225 SYSBA(sigaltstack, 0),
6226 SYSBA(rt_sigaction, 0),
6227 SYSBA(sigaction, 0),
6228 SYSBA(rt_sigprocmask, 0),
6229 SYSBA(sigprocmask, 0),
jsgf855d93d2003-10-13 22:26:55 +00006230#endif /* !SIGNAL_SIMULATION */
6231};
6232#define MAX_SYS_INFO (sizeof(sys_info)/sizeof(sys_info[0]))
6233
6234#undef SYSB_
6235#undef SYSBA
6236
6237Bool VG_(pre_syscall) ( ThreadId tid )
sewardjde4a1d02002-03-22 01:27:54 +00006238{
sewardj018f7622002-05-15 21:13:39 +00006239 ThreadState* tst;
jsgf855d93d2003-10-13 22:26:55 +00006240 UInt syscallno;
6241 const struct sys_info *sys;
6242 Bool special = False;
6243 Bool syscall_done = False; /* we actually ran the syscall */
sewardjde4a1d02002-03-22 01:27:54 +00006244
njn25e49d8e72002-09-23 09:36:25 +00006245 VGP_PUSHCC(VgpCoreSysWrap);
sewardjde4a1d02002-03-22 01:27:54 +00006246
jsgf855d93d2003-10-13 22:26:55 +00006247 tst = VG_(get_ThreadState)(tid);
sewardj018f7622002-05-15 21:13:39 +00006248
jsgf855d93d2003-10-13 22:26:55 +00006249 /* Convert vfork to fork, since we can't handle it otherwise. */
nethercote427e9512004-08-23 16:36:09 +00006250 if (SYSNO == __NR_vfork)
6251 SYSNO = __NR_fork;
sewardjde4a1d02002-03-22 01:27:54 +00006252
nethercote427e9512004-08-23 16:36:09 +00006253 syscallno = SYSNO;
jsgf855d93d2003-10-13 22:26:55 +00006254
6255 if (tst->syscallno != -1)
6256 VG_(printf)("tid %d has syscall %d\n", tst->tid, tst->syscallno);
6257
6258 vg_assert(tst->syscallno == -1); /* should be no current syscall */
6259 vg_assert(tst->status == VgTs_Runnable); /* should be runnable */
6260
6261 /* the syscall no is in %eax. For syscalls with <= 6 args,
6262 args 1 .. 6 to the syscall are in %ebx %ecx %edx %esi %edi %ebp.
6263 For calls with > 6 args, %ebx points to a lump of memory
sewardjde4a1d02002-03-22 01:27:54 +00006264 containing the args.
6265
6266 The result is returned in %eax. If this value >= 0, the call
6267 succeeded, and this is the return value. If < 0, it failed, and
6268 the negation of this value is errno. To be more specific,
6269 if res is in the range -EMEDIUMTYPE (-124) .. -EPERM (-1)
6270 (kernel 2.4.9 sources, include/asm-i386/errno.h)
6271 then it indicates an error. Otherwise it doesn't.
6272
6273 Dirk Mueller (mueller@kde.org) says that values -4095 .. -1
6274 (inclusive?) indicate error returns. Not sure where the -4095
6275 comes from.
6276 */
6277
jsgf855d93d2003-10-13 22:26:55 +00006278 tst->syscallno = syscallno;
fitzhardingef0f911c2003-11-09 09:51:33 +00006279 vg_assert(tst->status == VgTs_Runnable);
sewardjde4a1d02002-03-22 01:27:54 +00006280
jsgf855d93d2003-10-13 22:26:55 +00006281 if (syscallno < MAX_SPECIAL_SYS && special_sys[syscallno].before != NULL) {
6282 sys = &special_sys[syscallno];
6283 special = True;
6284 } else if (syscallno < MAX_SYS_INFO && sys_info[syscallno].before != NULL) {
6285 sys = &sys_info[syscallno];
6286 } else {
6287 sys = &bad_sys;
6288 special = True;
sewardjde4a1d02002-03-22 01:27:54 +00006289 }
6290
thughesbaa46e52004-07-29 17:44:23 +00006291 tst->sys_flags = sys->flags;
6292
jsgf855d93d2003-10-13 22:26:55 +00006293 /* Do any pre-syscall actions */
6294 if (VG_(needs).syscall_wrapper) {
6295 VGP_PUSHCC(VgpSkinSysWrap);
thughesbaa46e52004-07-29 17:44:23 +00006296 tst->sys_pre_res = SK_(pre_syscall)(tid, syscallno, /*isBlocking*/(sys->flags & MayBlock) != 0);
jsgf855d93d2003-10-13 22:26:55 +00006297 VGP_POPCC(VgpSkinSysWrap);
6298 }
6299
6300 MAYBE_PRINTF("SYSCALL[%d,%d](%3d)%s%s:",
6301 VG_(getpid)(), tid, syscallno,
6302 special ? " special" : "",
thughesbaa46e52004-07-29 17:44:23 +00006303 (sys->flags & MayBlock) != 0 ? " blocking" : "");
jsgf855d93d2003-10-13 22:26:55 +00006304
6305 if (special) {
6306 /* "Special" syscalls are implemented by Valgrind internally,
6307 and do not generate real kernel calls. The expectation,
6308 therefore, is that the "before" function not only does the
6309 appropriate tests, but also performs the syscall itself and
6310 sets the result. Special syscalls cannot block. */
thughesbaa46e52004-07-29 17:44:23 +00006311 vg_assert((tst->sys_flags & MayBlock) == 0);
jsgf855d93d2003-10-13 22:26:55 +00006312
6313 (sys->before)(tst->tid, tst);
6314
thughesbaa46e52004-07-29 17:44:23 +00006315 vg_assert(tst->sys_flags == sys->flags);
6316
jsgf855d93d2003-10-13 22:26:55 +00006317 syscall_done = True;
6318 } else {
6319 (sys->before)(tst->tid, tst);
6320
nethercote427e9512004-08-23 16:36:09 +00006321 if ((Int)res <= 0) {
jsgf855d93d2003-10-13 22:26:55 +00006322 /* "before" decided the syscall wasn't viable, so don't do
6323 anything - just pretend the syscall happened. */
6324 syscall_done = True;
thughesbaa46e52004-07-29 17:44:23 +00006325 } else if ((tst->sys_flags & MayBlock) != 0) {
fitzhardinge33730212003-11-10 21:21:00 +00006326 /* Issue to worker. If we're waiting on the syscall because
6327 it's in the hands of the ProxyLWP, then set the thread
6328 state to WaitSys. */
6329 tst->status = VgTs_WaitSys;
jsgf855d93d2003-10-13 22:26:55 +00006330 VG_(sys_issue)(tid);
6331 } else {
6332 /* run the syscall directly */
nethercotea4670f62004-08-23 16:39:42 +00006333 res = VG_(do_syscall)(syscallno, arg1, arg2, arg3, arg4, arg5, arg6);
jsgf855d93d2003-10-13 22:26:55 +00006334 syscall_done = True;
6335 }
6336 }
6337
6338 VGP_POPCC(VgpCoreSysWrap);
6339
fitzhardinge33730212003-11-10 21:21:00 +00006340 vg_assert(( syscall_done && tst->status == VgTs_Runnable) ||
6341 (!syscall_done && tst->status == VgTs_WaitSys ));
fitzhardingef0f911c2003-11-09 09:51:33 +00006342
jsgf855d93d2003-10-13 22:26:55 +00006343 return syscall_done;
6344}
6345
nethercote85cdd342004-08-01 22:36:40 +00006346static void restart_syscall(ThreadId tid)
6347{
6348 ThreadState* tst;
6349 tst = VG_(get_ThreadState)(tid);
6350
6351 vg_assert(tst != NULL);
6352 vg_assert(tst->status == VgTs_WaitSys);
6353 vg_assert(tst->syscallno != -1);
6354
nethercote427e9512004-08-23 16:36:09 +00006355 SYSNO = tst->syscallno;
nethercote41c75da2004-10-18 15:34:14 +00006356 VGA_(restart_syscall)(&tst->arch);
nethercote85cdd342004-08-01 22:36:40 +00006357}
jsgf855d93d2003-10-13 22:26:55 +00006358
fitzhardinge31ba9052004-01-16 02:15:23 +00006359void VG_(post_syscall) ( ThreadId tid, Bool restart )
jsgf855d93d2003-10-13 22:26:55 +00006360{
6361 ThreadState* tst;
6362 UInt syscallno;
6363 const struct sys_info *sys;
6364 Bool special = False;
fitzhardinge31ba9052004-01-16 02:15:23 +00006365 Bool restarted = False;
jsgf855d93d2003-10-13 22:26:55 +00006366 void *pre_res;
6367
6368 VGP_PUSHCC(VgpCoreSysWrap);
6369
6370 tst = VG_(get_ThreadState)(tid);
6371
nethercote996901a2004-08-03 13:29:09 +00006372 /* Tell the tool about the syscall return value */
nethercote427e9512004-08-23 16:36:09 +00006373 SET_SYSCALL_RETVAL(tst->tid, res);
jsgf855d93d2003-10-13 22:26:55 +00006374
6375 syscallno = tst->syscallno;
6376 pre_res = tst->sys_pre_res;
6377
6378 vg_assert(syscallno != -1); /* must be a current syscall */
jsgf855d93d2003-10-13 22:26:55 +00006379
6380 if (syscallno < MAX_SPECIAL_SYS && special_sys[syscallno].before != NULL) {
6381 sys = &special_sys[syscallno];
6382 special = True;
6383 } else if (syscallno < MAX_SYS_INFO && sys_info[syscallno].before != NULL) {
6384 sys = &sys_info[syscallno];
6385 } else {
6386 sys = &bad_sys;
6387 special = True;
6388 }
fitzhardingef0f911c2003-11-09 09:51:33 +00006389
nethercote427e9512004-08-23 16:36:09 +00006390 if (res == -VKI_ERESTARTSYS) {
fitzhardinge31ba9052004-01-16 02:15:23 +00006391 /* Applications never expect to see this, so we should either
6392 restart the syscall or fail it with EINTR, depending on what
6393 our caller wants. Generally they'll want to restart, but if
6394 client set the signal state to not restart, then we fail with
6395 EINTR. Either way, ERESTARTSYS means the syscall made no
6396 progress, and so can be failed or restarted without
6397 consequence. */
6398 if (0)
6399 VG_(printf)("syscall %d returned ERESTARTSYS; restart=%d\n",
6400 syscallno, restart);
6401
6402 if (restart) {
6403 restarted = True;
nethercote85cdd342004-08-01 22:36:40 +00006404 restart_syscall(tid);
fitzhardinge31ba9052004-01-16 02:15:23 +00006405 } else
nethercotea4670f62004-08-23 16:39:42 +00006406 res = -VKI_EINTR;
fitzhardinge31ba9052004-01-16 02:15:23 +00006407 }
6408
6409 if (!restarted) {
thughesbaa46e52004-07-29 17:44:23 +00006410 if (sys->after != NULL &&
nethercote427e9512004-08-23 16:36:09 +00006411 ((tst->sys_flags & PostOnFail) != 0 || !VG_(is_kerror)(res)))
fitzhardinge31ba9052004-01-16 02:15:23 +00006412 (sys->after)(tst->tid, tst);
6413
6414 /* Do any post-syscall actions
6415
6416 NOTE: this is only called if the syscall completed. If the
6417 syscall was restarted, then it will call the Tool's
6418 pre_syscall again, without calling post_syscall (ie, more
6419 pre's than post's)
6420 */
6421 if (VG_(needs).syscall_wrapper) {
6422 VGP_PUSHCC(VgpSkinSysWrap);
nethercote427e9512004-08-23 16:36:09 +00006423 SK_(post_syscall)(tid, syscallno, pre_res, res, /*isBlocking*/True); // did block
fitzhardinge31ba9052004-01-16 02:15:23 +00006424 VGP_POPCC(VgpSkinSysWrap);
6425 }
fitzhardingee1c06d82003-10-30 07:21:44 +00006426 }
6427
jsgf855d93d2003-10-13 22:26:55 +00006428 tst->status = VgTs_Runnable; /* runnable again */
fitzhardinge31ba9052004-01-16 02:15:23 +00006429 tst->syscallno = -1; /* no current syscall */
sewardj2e93c502002-04-12 11:12:52 +00006430
njn25e49d8e72002-09-23 09:36:25 +00006431 VGP_POPCC(VgpCoreSysWrap);
sewardj2e93c502002-04-12 11:12:52 +00006432}
6433
nethercote427e9512004-08-23 16:36:09 +00006434#undef SYSNO
6435#undef res
6436#undef arg1
6437#undef arg2
6438#undef arg3
6439#undef arg4
6440#undef arg5
6441#undef arg6
6442
sewardjde4a1d02002-03-22 01:27:54 +00006443/*--------------------------------------------------------------------*/
njn87ef6a62003-08-14 15:23:55 +00006444/*--- end vg_syscalls.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00006445/*--------------------------------------------------------------------*/
njnb94b81e2003-09-09 11:27:59 +00006446