blob: 2b4f89a6bf4a6e94f16242eed0c57d3d86949b4e [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
31#include "vg_include.h"
32
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
njn25e49d8e72002-09-23 09:36:25 +000040 * notify the skin 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/* ---------------------------------------------------------------------
58 A simple atfork() facility for Valgrind's internal use
59 ------------------------------------------------------------------ */
60
61struct atfork {
62 vg_atfork_t pre;
63 vg_atfork_t parent;
64 vg_atfork_t child;
65};
66
67#define VG_MAX_ATFORK 10
68
69static struct atfork atforks[VG_MAX_ATFORK];
70static Int n_atfork;
71
72void VG_(atfork)(vg_atfork_t pre, vg_atfork_t parent, vg_atfork_t child)
73{
74 Int i;
75
76 for(i = 0; i < n_atfork; i++) {
77 if (atforks[i].pre == pre &&
78 atforks[i].parent == parent &&
79 atforks[i].child == child)
80 return;
81 }
82
83 if (n_atfork >= VG_MAX_ATFORK)
84 VG_(core_panic)("Too many VG_(atfork) handlers requested: raise VG_MAX_ATFORK");
85
86 atforks[n_atfork].pre = pre;
87 atforks[n_atfork].parent = parent;
88 atforks[n_atfork].child = child;
89
90 n_atfork++;
91}
92
93static void do_atfork_pre(ThreadId tid)
94{
95 Int i;
96
97 for(i = 0; i < n_atfork; i++)
98 if (atforks[i].pre != NULL)
99 (*atforks[i].pre)(tid);
100}
101
102static void do_atfork_parent(ThreadId tid)
103{
104 Int i;
105
106 for(i = 0; i < n_atfork; i++)
107 if (atforks[i].parent != NULL)
108 (*atforks[i].parent)(tid);
109}
110
111static void do_atfork_child(ThreadId tid)
112{
113 Int i;
114
115 for(i = 0; i < n_atfork; i++)
116 if (atforks[i].child != NULL)
117 (*atforks[i].child)(tid);
118}
119
fitzhardinge1a303042003-12-22 08:48:50 +0000120/* return true if address range entirely contained within client
121 address space */
122static Bool valid_client_addr(Addr start, UInt size, ThreadId tid, const Char *syscall)
123{
124 Addr end = start+size;
125 Addr cl_base = VG_(client_base);
126 Bool ret;
127
128 if (size == 0)
129 return True;
130
131 if (cl_base < 0x10000)
132 cl_base = 0x10000;
133
134 ret =
135 (end >= start) &&
136 start >= cl_base && start < VG_(client_end) &&
137 (end <= VG_(client_end));
138
139 if (0)
140 VG_(printf)("%s: test=%p-%p client=%p-%p ret=%d\n",
141 syscall, start, end, cl_base, VG_(client_end), ret);
142
143 if (!ret && syscall != NULL) {
144 VG_(message)(Vg_UserMsg, "Warning: client syscall %s tried to modify addresses %p-%p",
145 syscall, start, end);
146
147 if (VG_(clo_verbosity) > 1) {
148 ExeContext *ec = VG_(get_ExeContext)(tid);
149 VG_(pp_ExeContext)(ec);
150 }
151 }
152
153 return ret;
154}
155
nethercote71980f02004-01-24 18:18:54 +0000156/* Walk through a colon-separated environment variable, and remove the
157 entries which matches file_pattern. It slides everything down over
158 the removed entries, and pads the remaining space with '\0'. It
159 modifies the entries in place (in the client address space), but it
160 shouldn't matter too much, since we only do this just before an
161 execve().
162
163 This is also careful to mop up any excess ':'s, since empty strings
164 delimited by ':' are considered to be '.' in a path.
165*/
nethercoteff9721d2004-01-26 17:10:01 +0000166void VG_(mash_colon_env)(Char *varp, const Char *remove_pattern)
nethercote71980f02004-01-24 18:18:54 +0000167{
168 Char *const start = varp;
169 Char *entry_start = varp;
170 Char *output = varp;
171
172 if (varp == NULL)
173 return;
174
175 while(*varp) {
176 if (*varp == ':') {
177 Char prev;
178 Bool match;
179
180 /* This is a bit subtle: we want to match against the entry
181 we just copied, because it may have overlapped with
182 itself, junking the original. */
183
184 prev = *output;
185 *output = '\0';
186
187 match = VG_(string_match)(remove_pattern, entry_start);
188
189 *output = prev;
190
191 if (match) {
192 output = entry_start;
193 varp++; /* skip ':' after removed entry */
194 } else
195 entry_start = output+1; /* entry starts after ':' */
196 }
197
198 *output++ = *varp++;
199 }
200
201 /* match against the last entry */
202 if (VG_(string_match)(remove_pattern, entry_start)) {
203 output = entry_start;
204 if (output > start) {
205 /* remove trailing ':' */
206 output--;
207 vg_assert(*output == ':');
208 }
209 }
210
211 /* pad out the left-overs with '\0' */
212 while(output < varp)
213 *output++ = '\0';
214}
215
216
njn25e49d8e72002-09-23 09:36:25 +0000217/* ---------------------------------------------------------------------
nethercote27ea8bc2004-07-10 17:21:14 +0000218 Doing mmap, mremap
njn25e49d8e72002-09-23 09:36:25 +0000219 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000220
njn25e49d8e72002-09-23 09:36:25 +0000221// Nb: this isn't done as precisely as possible, but it seems that programs
222// are usually sufficiently well-behaved that the more obscure corner cases
223// aren't important. Various comments in the few functions below give more
224// details... njn 2002-Sep-17
225
226/* AFAICT from kernel sources (mm/mprotect.c) and general experimentation,
227 munmap, mprotect (and mremap??) work at the page level. So addresses
228 and lengths must be adjusted for this. */
229
230/* Mash around start and length so that the area exactly covers
231 an integral number of pages. If we don't do that, memcheck's
232 idea of addressible memory diverges from that of the
233 kernel's, which causes the leak detector to crash. */
234static
235void mash_addr_and_len( Addr* a, UInt* len)
sewardjde4a1d02002-03-22 01:27:54 +0000236{
fitzhardinge98abfc72003-12-16 02:05:15 +0000237 Addr ra;
238
239 ra = PGROUNDDN(*a);
240 *len = PGROUNDUP(*a + *len) - ra;
241 *a = ra;
sewardjde4a1d02002-03-22 01:27:54 +0000242}
243
244static
fitzhardinge98abfc72003-12-16 02:05:15 +0000245void mmap_segment ( Addr a, UInt len, UInt prot, UInt mm_flags, Int fd, ULong offset )
sewardjde4a1d02002-03-22 01:27:54 +0000246{
sewardj40f8ebe2002-10-23 21:46:13 +0000247 Bool rr, ww, xx;
fitzhardinge98abfc72003-12-16 02:05:15 +0000248 UInt flags;
njn25e49d8e72002-09-23 09:36:25 +0000249
fitzhardinge98abfc72003-12-16 02:05:15 +0000250 flags = SF_MMAP;
251
252 if (mm_flags & VKI_MAP_FIXED)
253 flags |= SF_FIXED;
254 if (!(mm_flags & VKI_MAP_PRIVATE))
255 flags |= SF_SHARED;
256
257 if (fd != -1)
258 flags |= SF_FILE;
259
260 VG_(map_fd_segment)(a, len, prot, flags, fd, offset, NULL);
njn25e49d8e72002-09-23 09:36:25 +0000261
fitzhardinge1a303042003-12-22 08:48:50 +0000262 rr = prot & VKI_PROT_READ;
263 ww = prot & VKI_PROT_WRITE;
264 xx = prot & VKI_PROT_EXEC;
njn25e49d8e72002-09-23 09:36:25 +0000265
sewardj40f8ebe2002-10-23 21:46:13 +0000266 VG_TRACK( new_mem_mmap, a, len, rr, ww, xx );
sewardjde4a1d02002-03-22 01:27:54 +0000267}
268
njn25e49d8e72002-09-23 09:36:25 +0000269static
fitzhardinge1a303042003-12-22 08:48:50 +0000270Addr mremap_segment ( Addr old_addr, UInt old_size,
271 Addr new_addr, UInt new_size,
272 UInt flags, ThreadId tid)
njn25e49d8e72002-09-23 09:36:25 +0000273{
fitzhardinge1a303042003-12-22 08:48:50 +0000274 Addr ret;
275 Segment *seg, *next;
njn25e49d8e72002-09-23 09:36:25 +0000276
fitzhardinge1a303042003-12-22 08:48:50 +0000277 old_size = PGROUNDUP(old_size);
278 new_size = PGROUNDUP(new_size);
njn25e49d8e72002-09-23 09:36:25 +0000279
fitzhardinge1a303042003-12-22 08:48:50 +0000280 if (PGROUNDDN(old_addr) != old_addr)
281 return -VKI_EINVAL;
282
283 if (!valid_client_addr(old_addr, old_size, tid, "mremap(old_addr)"))
284 return -VKI_EFAULT;
285
286 /* fixed at the current address means we don't move it */
287 if ((flags & VKI_MREMAP_FIXED) && (old_addr == new_addr))
288 flags &= ~(VKI_MREMAP_FIXED|VKI_MREMAP_MAYMOVE);
289
290 if (flags & VKI_MREMAP_FIXED) {
291 if (PGROUNDDN(new_addr) != new_addr)
292 return -VKI_EINVAL;
293
294 if (!valid_client_addr(new_addr, new_size, tid, "mremap(new_addr)"))
295 return -VKI_ENOMEM;
296
297 /* check for overlaps */
298 if ((old_addr < (new_addr+new_size) &&
299 (old_addr+old_size) > new_addr) ||
300 (new_addr < (old_addr+new_size) &&
301 (new_addr+new_size) > old_addr))
302 return -VKI_EINVAL;
njn25e49d8e72002-09-23 09:36:25 +0000303 }
fitzhardinge1a303042003-12-22 08:48:50 +0000304
305 /* Do nothing */
306 if (!(flags & VKI_MREMAP_FIXED) && new_size == old_size)
307 return old_addr;
308
309 seg = VG_(find_segment)(old_addr);
310
311 /* range must be contained within segment */
312 if (seg == NULL || !VG_(seg_contains)(seg, old_addr, old_size))
313 return -VKI_EINVAL;
314
315 next = VG_(next_segment)(seg);
316
317 if (0)
318 VG_(printf)("mremap: old_addr+new_size=%p next->addr=%p flags=%d\n",
319 old_addr+new_size, next->addr, flags);
320
321 if ((flags & VKI_MREMAP_FIXED) ||
322 (next != NULL && (old_addr+new_size) > next->addr)) {
323 /* we're moving the block */
324 Addr a;
325
326 if ((flags & (VKI_MREMAP_FIXED|VKI_MREMAP_MAYMOVE)) == 0)
327 return -VKI_ENOMEM; /* not allowed to move */
328
329 if ((flags & VKI_MREMAP_FIXED) == 0)
330 new_addr = 0;
331
332 a = VG_(find_map_space)(new_addr, new_size, True);
333
334 if ((flags & VKI_MREMAP_FIXED) && a != new_addr)
335 return -VKI_ENOMEM; /* didn't find the place we wanted */
336
337 new_addr = a;
338 ret = a;
339
340 /* we've nailed down the location */
341 flags |= VKI_MREMAP_FIXED|VKI_MREMAP_MAYMOVE;
342
343 ret = VG_(do_syscall)(__NR_mremap, old_addr, old_size, new_size,
344 flags, new_addr);
345
346 if (ret != new_addr) {
347 vg_assert(VG_(is_kerror)(ret));
348 return ret;
349 }
350
351 VG_TRACK(copy_mem_remap, old_addr, new_addr,
352 (old_size < new_size) ? old_size : new_size);
353
354 if (new_size > old_size)
355 VG_TRACK(new_mem_mmap, new_addr+old_size, new_size-old_size,
356 seg->prot & VKI_PROT_READ,
357 seg->prot & VKI_PROT_WRITE,
358 seg->prot & VKI_PROT_EXEC);
359 VG_TRACK(die_mem_munmap, old_addr, old_size);
360
361 VG_(map_file_segment)(new_addr, new_size,
362 seg->prot,
363 seg->flags,
364 seg->dev, seg->ino,
365 seg->offset, seg->filename);
366
367 VG_(munmap)((void *)old_addr, old_size);
368 } else {
369 /* staying in place */
370 ret = old_addr;
371
372 if (new_size < old_size) {
373 VG_TRACK(die_mem_munmap, old_addr+new_size, old_size-new_size);
374 VG_(munmap)((void *)(old_addr+new_size), old_size-new_size);
375 } else {
376 /* we've nailed down the location */
377 flags &= ~VKI_MREMAP_MAYMOVE;
378
379 if (0)
380 VG_(printf)("mremap: old_addr=%p old_size=%d new_size=%d flags=%d\n",
381 old_addr, old_size, new_size, flags);
382
383 ret = VG_(do_syscall)(__NR_mremap, old_addr, old_size, new_size,
384 flags, 0);
385
386 if (ret != old_addr)
387 return ret;
388
389 VG_TRACK(new_mem_mmap, old_addr+old_size, new_size-old_size,
390 seg->prot & VKI_PROT_READ,
391 seg->prot & VKI_PROT_WRITE,
392 seg->prot & VKI_PROT_EXEC);
393
394 VG_(map_file_segment)(old_addr+old_size, new_size-old_size,
395 seg->prot,
396 seg->flags,
397 seg->dev, seg->ino,
398 seg->offset, seg->filename);
399 }
400 }
401
402 return ret;
sewardjde4a1d02002-03-22 01:27:54 +0000403}
404
405
406/* Is this a Linux kernel error return value? */
407/* From:
408 http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/sysdeps/unix/sysv/
409 linux/i386/sysdep.h?
410 rev=1.28&content-type=text/x-cvsweb-markup&cvsroot=glibc
411
njn25e49d8e72002-09-23 09:36:25 +0000412 \begin{quote}:
sewardjde4a1d02002-03-22 01:27:54 +0000413
414 Linux uses a negative return value to indicate syscall errors,
415 unlike most Unices, which use the condition codes' carry flag.
416
417 Since version 2.1 the return value of a system call might be
418 negative even if the call succeeded. E.g., the `lseek' system call
419 might return a large offset. Therefore we must not anymore test
420 for < 0, but test for a real error by making sure the value in %eax
421 is a real error number. Linus said he will make sure the no syscall
daywalker7e73e5f2003-07-04 16:18:15 +0000422 returns a value in -1 .. -4095 as a valid result so we can safely
sewardjde4a1d02002-03-22 01:27:54 +0000423 test with -4095.
424
425 END QUOTE
426*/
427Bool VG_(is_kerror) ( Int res )
428{
429 if (res >= -4095 && res <= -1)
430 return True;
431 else
432 return False;
433}
434
rjwalshf5f536f2003-11-17 17:45:00 +0000435/* One of these is allocated for each open file descriptor. */
436
437typedef struct OpenFd
438{
439 Int fd; /* The file descriptor */
440 Char *pathname; /* NULL if not a regular file or unknown */
441 ExeContext *where; /* NULL if inherited from parent */
442 struct OpenFd *next, *prev;
443} OpenFd;
444
445/* List of allocated file descriptors. */
446
447static OpenFd *allocated_fds;
448
449/* Count of open file descriptors. */
450
451static int fd_count = 0;
452
nethercoteccc9ecd2004-07-16 17:32:15 +0000453/* Given a file descriptor, attempt to deduce its filename. To do this,
rjwalshf5f536f2003-11-17 17:45:00 +0000454 we use /proc/self/fd/<FD>. If this doesn't point to a file, or if it
455 doesn't exist, we just return NULL. Otherwise, we return a pointer
456 to the file name, which the caller is responsible for freeing. */
457
fitzhardinge98abfc72003-12-16 02:05:15 +0000458Char *VG_(resolve_filename)(Int fd)
rjwalshf5f536f2003-11-17 17:45:00 +0000459{
460 char tmp[28], buf[PATH_MAX];
461
462 VG_(sprintf)(tmp, "/proc/self/fd/%d", fd);
463 VG_(memset)(buf, 0, PATH_MAX);
464
465 if(VG_(readlink)(tmp, buf, PATH_MAX) == -1)
466 return NULL;
467
fitzhardingea7728472003-12-16 01:48:38 +0000468 return ((buf[0] == '/') ? VG_(arena_strdup)(VG_AR_CORE, buf) : NULL);
rjwalshf5f536f2003-11-17 17:45:00 +0000469}
470
471
472/* Note the fact that a file descriptor was just closed. */
473
474static
475void record_fd_close(Int tid, Int fd)
476{
477 OpenFd *i = allocated_fds;
478
thughesad1c9562004-06-26 11:27:52 +0000479 if (fd >= VG_(fd_hard_limit))
rjwalsh02665ba2003-12-18 01:48:06 +0000480 return; /* Valgrind internal */
481
rjwalshf5f536f2003-11-17 17:45:00 +0000482 while(i) {
483 if(i->fd == fd) {
484 if(i->prev)
485 i->prev->next = i->next;
486 else
487 allocated_fds = i->next;
488 if(i->next)
489 i->next->prev = i->prev;
490 if(i->pathname)
fitzhardingea7728472003-12-16 01:48:38 +0000491 VG_(arena_free) (VG_AR_CORE, i->pathname);
492 VG_(arena_free) (VG_AR_CORE, i);
rjwalshf5f536f2003-11-17 17:45:00 +0000493 fd_count--;
494 break;
495 }
496 i = i->next;
497 }
498}
499
500/* Note the fact that a file descriptor was just opened. If the
501 tid is -1, this indicates an inherited fd. If the pathname is NULL,
502 this either indicates a non-standard file (i.e. a pipe or socket or
503 some such thing) or that we don't know the filename. If the fd is
504 already open, then we're probably doing a dup2() to an existing fd,
505 so just overwrite the existing one. */
506
507static
508void record_fd_open(Int tid, Int fd, char *pathname)
509{
510 OpenFd *i;
511
thughesad1c9562004-06-26 11:27:52 +0000512 if (fd >= VG_(fd_hard_limit))
fitzhardinge0e8bfcf2003-12-12 07:46:54 +0000513 return; /* Valgrind internal */
514
rjwalshf5f536f2003-11-17 17:45:00 +0000515 /* Check to see if this fd is already open. */
516 i = allocated_fds;
517 while (i) {
518 if (i->fd == fd) {
fitzhardingea7728472003-12-16 01:48:38 +0000519 if (i->pathname) VG_(arena_free)(VG_AR_CORE, i->pathname);
rjwalshf5f536f2003-11-17 17:45:00 +0000520 break;
521 }
522 i = i->next;
523 }
524
525 /* Not already one: allocate an OpenFd */
526 if (i == NULL) {
fitzhardingea7728472003-12-16 01:48:38 +0000527 i = VG_(arena_malloc)(VG_AR_CORE, sizeof(OpenFd));
rjwalshf5f536f2003-11-17 17:45:00 +0000528
529 i->prev = NULL;
530 i->next = allocated_fds;
531 if(allocated_fds) allocated_fds->prev = i;
532 allocated_fds = i;
533 fd_count++;
534 }
535
536 i->fd = fd;
537 i->pathname = pathname;
538 i->where = (tid == -1) ? NULL : VG_(get_ExeContext)(tid);
539}
540
541static
542Char *unix2name(struct sockaddr_un *sa, UInt len, Char *name)
543{
544 if(sa == NULL || len == 0 || sa->sun_path[0] == '\0') {
545 VG_(sprintf)(name, "<unknown>");
546 } else {
547 VG_(sprintf)(name, "%s", sa->sun_path);
548 }
549
550 return name;
551}
552
553static
554Char *inet2name(struct sockaddr_in *sa, UInt len, Char *name)
555{
556 if(sa == NULL || len == 0) {
557 VG_(sprintf)(name, "<unknown>");
558 } else {
559 UInt addr = sa->sin_addr.s_addr;
560
561 if (addr == 0) {
562 VG_(sprintf)(name, "<unbound>");
563 } else {
564 VG_(sprintf)(name, "%u.%u.%u.%u:%u",
565 addr & 0xFF, (addr>>8) & 0xFF,
566 (addr>>16) & 0xFF, (addr>>24) & 0xFF,
nethercote4ef5c392004-01-20 14:43:42 +0000567 ntohs(sa->sin_port));
rjwalshf5f536f2003-11-17 17:45:00 +0000568 }
569 }
570
571 return name;
572}
573
574
575/*
576 * Try get some details about a socket.
577 */
578
579static void
580getsockdetails(int fd)
581{
582 union u {
583 struct sockaddr a;
584 struct sockaddr_in in;
585 struct sockaddr_un un;
586 } laddr;
587 socklen_t llen;
588
589 llen = sizeof(laddr);
590 VG_(memset)(&laddr, 0, llen);
591
592 if(VG_(getsockname)(fd, (struct vki_sockaddr *)&(laddr.a), &llen) != -1) {
593 switch(laddr.a.sa_family) {
594 case AF_INET: {
595 static char lname[32];
596 static char pname[32];
597 struct sockaddr_in paddr;
598 socklen_t plen = sizeof(struct sockaddr_in);
599
600 if(VG_(getpeername)(fd, (struct vki_sockaddr *)&paddr, &plen) != -1) {
601 VG_(message)(Vg_UserMsg, "Open AF_INET socket %d: %s <-> %s", fd,
602 inet2name(&(laddr.in), llen, lname),
603 inet2name(&paddr, plen, pname));
604 } else {
605 VG_(message)(Vg_UserMsg, "Open AF_INET socket %d: %s <-> unbound",
606 fd, inet2name(&(laddr.in), llen, lname));
607 }
608 return;
609 }
610 case AF_UNIX: {
611 static char lname[256];
612 VG_(message)(Vg_UserMsg, "Open AF_UNIX socket %d: %s", fd,
613 unix2name(&(laddr.un), llen, lname));
614 return;
615 }
616 default:
617 VG_(message)(Vg_UserMsg, "Open pf-%d socket %d:",
618 laddr.a.sa_family, fd);
619 return;
620 }
621 }
622
623 VG_(message)(Vg_UserMsg, "Open socket %d:", fd);
624}
625
626
627/* Dump out a summary, and optionally a more detailed list, of open file
628 descriptors. */
629
630void VG_(fd_stats) ()
631{
632 OpenFd *i = allocated_fds;
633
634 VG_(message)(Vg_UserMsg,
635 "FILE DESCRIPTORS: %d open at exit.", fd_count);
636
637 while(i) {
638 if(i->pathname) {
639 VG_(message)(Vg_UserMsg, "Open file descriptor %d: %s", i->fd,
640 i->pathname);
641 } else {
642 int val;
643 socklen_t len = sizeof(val);
644
645 if(VG_(getsockopt)(i->fd, SOL_SOCKET, SO_TYPE, &val, &len) == -1) {
646 VG_(message)(Vg_UserMsg, "Open file descriptor %d:", i->fd);
647 } else {
648 getsockdetails(i->fd);
649 }
650 }
651
652 if(i->where) {
653 VG_(pp_ExeContext)(i->where);
654 VG_(message)(Vg_UserMsg, "");
655 } else {
656 VG_(message)(Vg_UserMsg, " <inherited from parent>");
657 VG_(message)(Vg_UserMsg, "");
658 }
659
660 i = i->next;
661 }
662
663 VG_(message)(Vg_UserMsg, "");
664}
665
666/* If /proc/self/fd doesn't exist for some weird reason (like you've
667 got a kernel that doesn't have /proc support compiled in), then we
668 need to find out what file descriptors we inherited from our parent
669 process the hard way - by checking each fd in turn. */
670
671static
672void do_hacky_preopened()
673{
674 struct vki_rlimit lim;
675 unsigned int count;
676 int i;
677
678 if(VG_(getrlimit) (VKI_RLIMIT_NOFILE, &lim) == -1) {
679 /* Hmm. getrlimit() failed. Now we're screwed, so just choose
680 an arbitrarily high number. 1024 happens to be the limit in
681 the 2.4 kernels. */
682 count = 1024;
683 } else {
684 count = lim.rlim_cur;
685 }
686
687 for (i = 0; i < count; i++)
688 if(VG_(fcntl)(i, VKI_F_GETFL, 0) != -1)
689 record_fd_open(-1, i, NULL);
690}
691
692/* Initialize the list of open file descriptors with the file descriptors
693 we inherited from out parent process. */
694
695void VG_(init_preopened_fds)()
696{
697 int f, ret;
698 struct vki_dirent d;
699
700 f = VG_(open)("/proc/self/fd", VKI_O_RDONLY, 0);
701 if(f == -1) {
702 do_hacky_preopened();
703 return;
704 }
705
706 while((ret = VG_(getdents)(f, &d, sizeof(d))) != 0) {
707 if(ret == -1)
708 goto out;
709
710 if(VG_(strcmp)(d.d_name, ".") && VG_(strcmp)(d.d_name, "..")) {
711 int fno = VG_(atoll)(d.d_name);
712
713 if(fno != f)
714 if(VG_(clo_track_fds))
fitzhardinge98abfc72003-12-16 02:05:15 +0000715 record_fd_open(-1, fno, VG_(resolve_filename)(fno));
rjwalshf5f536f2003-11-17 17:45:00 +0000716 }
717
718 VG_(lseek)(f, d.d_off, VKI_SEEK_SET);
719 }
720
721out:
722 VG_(close)(f);
723}
724
sewardjde4a1d02002-03-22 01:27:54 +0000725static
726UInt get_shm_size ( Int shmid )
727{
728 struct shmid_ds buf;
jsgf855d93d2003-10-13 22:26:55 +0000729 long __res = VG_(do_syscall)(__NR_ipc, 24 /* IPCOP_shmctl */, shmid, IPC_STAT, 0, &buf);
sewardjde4a1d02002-03-22 01:27:54 +0000730 if ( VG_(is_kerror) ( __res ) )
731 return 0;
732
733 return buf.shm_segsz;
734}
735
736static
sewardj8c824512002-04-14 04:16:48 +0000737Char *strdupcat ( const Char *s1, const Char *s2, ArenaId aid )
sewardjde4a1d02002-03-22 01:27:54 +0000738{
739 UInt len = VG_(strlen) ( s1 ) + VG_(strlen) ( s2 ) + 1;
njn25e49d8e72002-09-23 09:36:25 +0000740 Char *result = VG_(arena_malloc) ( aid, len );
sewardjde4a1d02002-03-22 01:27:54 +0000741 VG_(strcpy) ( result, s1 );
742 VG_(strcat) ( result, s2 );
743 return result;
744}
745
746static
jsgf855d93d2003-10-13 22:26:55 +0000747void pre_mem_read_sendmsg ( ThreadId tid,
748 Char *msg, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +0000749{
750 Char *outmsg = strdupcat ( "socketcall.sendmsg", msg, VG_AR_TRANSIENT );
njn72718642003-07-24 08:45:32 +0000751 SYSCALL_TRACK( pre_mem_read, tid, outmsg, base, size );
njn25e49d8e72002-09-23 09:36:25 +0000752
753 VG_(arena_free) ( VG_AR_TRANSIENT, outmsg );
sewardjde4a1d02002-03-22 01:27:54 +0000754}
755
756static
jsgf855d93d2003-10-13 22:26:55 +0000757void pre_mem_write_recvmsg ( ThreadId tid,
758 Char *msg, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +0000759{
760 Char *outmsg = strdupcat ( "socketcall.recvmsg", msg, VG_AR_TRANSIENT );
njn72718642003-07-24 08:45:32 +0000761 SYSCALL_TRACK( pre_mem_write, tid, outmsg, base, size );
njn25e49d8e72002-09-23 09:36:25 +0000762 VG_(arena_free) ( VG_AR_TRANSIENT, outmsg );
sewardjde4a1d02002-03-22 01:27:54 +0000763}
764
765static
njn72718642003-07-24 08:45:32 +0000766void post_mem_write_recvmsg ( ThreadId tid,
njn25e49d8e72002-09-23 09:36:25 +0000767 Char *fieldName, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +0000768{
njn25e49d8e72002-09-23 09:36:25 +0000769 VG_TRACK( post_mem_write, base, size );
sewardjde4a1d02002-03-22 01:27:54 +0000770}
771
772static
sewardj8c824512002-04-14 04:16:48 +0000773void msghdr_foreachfield (
njn72718642003-07-24 08:45:32 +0000774 ThreadId tid,
sewardj8c824512002-04-14 04:16:48 +0000775 struct msghdr *msg,
njn72718642003-07-24 08:45:32 +0000776 void (*foreach_func)( ThreadId, Char *, UInt, UInt )
sewardj8c824512002-04-14 04:16:48 +0000777 )
sewardjde4a1d02002-03-22 01:27:54 +0000778{
779 if ( !msg )
780 return;
781
njn72718642003-07-24 08:45:32 +0000782 foreach_func ( tid, "(msg)", (Addr)msg, sizeof( struct msghdr ) );
sewardjde4a1d02002-03-22 01:27:54 +0000783
784 if ( msg->msg_name )
njn72718642003-07-24 08:45:32 +0000785 foreach_func ( tid,
sewardj8c824512002-04-14 04:16:48 +0000786 "(msg.msg_name)",
sewardjde4a1d02002-03-22 01:27:54 +0000787 (Addr)msg->msg_name, msg->msg_namelen );
788
789 if ( msg->msg_iov ) {
790 struct iovec *iov = msg->msg_iov;
791 UInt i;
792
njn72718642003-07-24 08:45:32 +0000793 foreach_func ( tid,
sewardj8c824512002-04-14 04:16:48 +0000794 "(msg.msg_iov)",
sewardjde4a1d02002-03-22 01:27:54 +0000795 (Addr)iov, msg->msg_iovlen * sizeof( struct iovec ) );
796
797 for ( i = 0; i < msg->msg_iovlen; ++i, ++iov )
njn72718642003-07-24 08:45:32 +0000798 foreach_func ( tid,
sewardj8c824512002-04-14 04:16:48 +0000799 "(msg.msg_iov[i]",
sewardjde4a1d02002-03-22 01:27:54 +0000800 (Addr)iov->iov_base, iov->iov_len );
801 }
802
803 if ( msg->msg_control )
njn72718642003-07-24 08:45:32 +0000804 foreach_func ( tid,
sewardj8c824512002-04-14 04:16:48 +0000805 "(msg.msg_control)",
sewardjde4a1d02002-03-22 01:27:54 +0000806 (Addr)msg->msg_control, msg->msg_controllen );
807}
808
rjwalshf5f536f2003-11-17 17:45:00 +0000809void check_cmsg_for_fds(Int tid, struct msghdr *msg)
810{
811 struct cmsghdr *cm = CMSG_FIRSTHDR(msg);
812
813 while (cm) {
814 if (cm->cmsg_level == SOL_SOCKET &&
815 cm->cmsg_type == SCM_RIGHTS ) {
816 int *fds = (int *) CMSG_DATA(cm);
817 int fdc = (cm->cmsg_len - CMSG_ALIGN(sizeof(struct cmsghdr)))
818 / sizeof(int);
819 int i;
820
821 for (i = 0; i < fdc; i++)
822 if(VG_(clo_track_fds))
nethercote493dd182004-02-24 23:57:47 +0000823 // XXX: must we check the range on these fds with
824 // fd_allowed()?
fitzhardinge98abfc72003-12-16 02:05:15 +0000825 record_fd_open (tid, fds[i], VG_(resolve_filename)(fds[i]));
rjwalshf5f536f2003-11-17 17:45:00 +0000826 }
827
828 cm = CMSG_NXTHDR(msg, cm);
829 }
830}
831
sewardjc483e8f2002-05-03 21:01:35 +0000832static
jsgf855d93d2003-10-13 22:26:55 +0000833void pre_mem_read_sockaddr ( ThreadId tid,
834 Char *description,
835 struct sockaddr *sa, UInt salen )
sewardjc483e8f2002-05-03 21:01:35 +0000836{
sewardjff7c1ab2003-02-24 21:55:34 +0000837 Char *outmsg;
838
839 /* NULL/zero-length sockaddrs are legal */
840 if ( sa == NULL || salen == 0 ) return;
841
842 outmsg = VG_(arena_malloc) ( VG_AR_TRANSIENT,
843 strlen( description ) + 30 );
sewardjc483e8f2002-05-03 21:01:35 +0000844
845 VG_(sprintf) ( outmsg, description, ".sa_family" );
njn72718642003-07-24 08:45:32 +0000846 SYSCALL_TRACK( pre_mem_read, tid, outmsg,
sewardj09cbb222002-11-17 02:46:19 +0000847 (UInt) &sa->sa_family, sizeof (sa_family_t));
jsgf855d93d2003-10-13 22:26:55 +0000848
sewardjc483e8f2002-05-03 21:01:35 +0000849 switch (sa->sa_family) {
850
851 case AF_UNIX:
852 VG_(sprintf) ( outmsg, description, ".sun_path" );
njn72718642003-07-24 08:45:32 +0000853 SYSCALL_TRACK( pre_mem_read_asciiz, tid, outmsg,
sewardjc483e8f2002-05-03 21:01:35 +0000854 (UInt) ((struct sockaddr_un *) sa)->sun_path);
855 break;
856
857 case AF_INET:
858 VG_(sprintf) ( outmsg, description, ".sin_port" );
njn72718642003-07-24 08:45:32 +0000859 SYSCALL_TRACK( pre_mem_read, tid, outmsg,
sewardjc483e8f2002-05-03 21:01:35 +0000860 (UInt) &((struct sockaddr_in *) sa)->sin_port,
sewardj32102152002-05-04 10:28:17 +0000861 sizeof (((struct sockaddr_in *) sa)->sin_port));
sewardjc483e8f2002-05-03 21:01:35 +0000862 VG_(sprintf) ( outmsg, description, ".sin_addr" );
njn72718642003-07-24 08:45:32 +0000863 SYSCALL_TRACK( pre_mem_read, tid, outmsg,
sewardjc483e8f2002-05-03 21:01:35 +0000864 (UInt) &((struct sockaddr_in *) sa)->sin_addr,
865 sizeof (struct in_addr));
866 break;
867
868 case AF_INET6:
869 VG_(sprintf) ( outmsg, description, ".sin6_port" );
njn72718642003-07-24 08:45:32 +0000870 SYSCALL_TRACK( pre_mem_read, tid, outmsg,
sewardjc483e8f2002-05-03 21:01:35 +0000871 (UInt) &((struct sockaddr_in6 *) sa)->sin6_port,
sewardj32102152002-05-04 10:28:17 +0000872 sizeof (((struct sockaddr_in6 *) sa)->sin6_port));
sewardjc483e8f2002-05-03 21:01:35 +0000873 VG_(sprintf) ( outmsg, description, ".sin6_flowinfo" );
njn72718642003-07-24 08:45:32 +0000874 SYSCALL_TRACK( pre_mem_read, tid, outmsg,
sewardjc483e8f2002-05-03 21:01:35 +0000875 (UInt) &((struct sockaddr_in6 *) sa)->sin6_flowinfo,
876 sizeof (uint32_t));
877 VG_(sprintf) ( outmsg, description, ".sin6_addr" );
njn72718642003-07-24 08:45:32 +0000878 SYSCALL_TRACK( pre_mem_read, tid, outmsg,
sewardjc483e8f2002-05-03 21:01:35 +0000879 (UInt) &((struct sockaddr_in6 *) sa)->sin6_addr,
880 sizeof (struct in6_addr));
sewardj32102152002-05-04 10:28:17 +0000881# ifndef GLIBC_2_1
sewardjc483e8f2002-05-03 21:01:35 +0000882 VG_(sprintf) ( outmsg, description, ".sin6_scope_id" );
njn72718642003-07-24 08:45:32 +0000883 SYSCALL_TRACK( pre_mem_read, tid, outmsg,
sewardjc483e8f2002-05-03 21:01:35 +0000884 (UInt) &((struct sockaddr_in6 *) sa)->sin6_scope_id,
jsgf855d93d2003-10-13 22:26:55 +0000885 sizeof (uint32_t));
sewardj32102152002-05-04 10:28:17 +0000886# endif
sewardjc483e8f2002-05-03 21:01:35 +0000887 break;
888
889 default:
890 VG_(sprintf) ( outmsg, description, "" );
njn72718642003-07-24 08:45:32 +0000891 SYSCALL_TRACK( pre_mem_read, tid, outmsg, (UInt) sa, salen );
sewardjc483e8f2002-05-03 21:01:35 +0000892 break;
893 }
894
njn25e49d8e72002-09-23 09:36:25 +0000895 VG_(arena_free) ( VG_AR_TRANSIENT, outmsg );
sewardjc483e8f2002-05-03 21:01:35 +0000896}
897
njn25e49d8e72002-09-23 09:36:25 +0000898/* Dereference a pointer to a UInt. */
njn72718642003-07-24 08:45:32 +0000899static UInt deref_UInt ( ThreadId tid, Addr a, Char* s )
njn25e49d8e72002-09-23 09:36:25 +0000900{
901 UInt* a_p = (UInt*)a;
njn72718642003-07-24 08:45:32 +0000902 SYSCALL_TRACK( pre_mem_read, tid, s, (Addr)a_p, sizeof(UInt) );
njn25e49d8e72002-09-23 09:36:25 +0000903 if (a_p == NULL)
904 return 0;
905 else
906 return *a_p;
907}
908
909/* Dereference a pointer to a pointer. */
njn72718642003-07-24 08:45:32 +0000910static Addr deref_Addr ( ThreadId tid, Addr a, Char* s )
njn25e49d8e72002-09-23 09:36:25 +0000911{
912 Addr* a_p = (Addr*)a;
njn72718642003-07-24 08:45:32 +0000913 SYSCALL_TRACK( pre_mem_read, tid, s, (Addr)a_p, sizeof(Addr) );
njn25e49d8e72002-09-23 09:36:25 +0000914 return *a_p;
915}
916
917static
njn72718642003-07-24 08:45:32 +0000918void buf_and_len_pre_check( ThreadId tid, Addr buf_p, Addr buflen_p,
njn25e49d8e72002-09-23 09:36:25 +0000919 Char* buf_s, Char* buflen_s )
920{
fitzhardinge98abfc72003-12-16 02:05:15 +0000921 if (VG_(defined_pre_mem_write)()) {
njn72718642003-07-24 08:45:32 +0000922 UInt buflen_in = deref_UInt( tid, buflen_p, buflen_s);
njn25e49d8e72002-09-23 09:36:25 +0000923 if (buflen_in > 0) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000924 SK_(pre_mem_write) ( Vg_CoreSysCall,
925 tid, buf_s, buf_p, buflen_in );
njn25e49d8e72002-09-23 09:36:25 +0000926 }
927 }
928}
929
930static
njn72718642003-07-24 08:45:32 +0000931void buf_and_len_post_check( ThreadId tid, Int res,
njn25e49d8e72002-09-23 09:36:25 +0000932 Addr buf_p, Addr buflen_p, Char* s )
933{
fitzhardinge98abfc72003-12-16 02:05:15 +0000934 if (!VG_(is_kerror)(res) && VG_(defined_post_mem_write)()) {
njn72718642003-07-24 08:45:32 +0000935 UInt buflen_out = deref_UInt( tid, buflen_p, s);
njn25e49d8e72002-09-23 09:36:25 +0000936 if (buflen_out > 0 && buf_p != (Addr)NULL) {
fitzhardinge98abfc72003-12-16 02:05:15 +0000937 SK_(post_mem_write) ( buf_p, buflen_out );
njn25e49d8e72002-09-23 09:36:25 +0000938 }
939 }
940}
941
942/* ---------------------------------------------------------------------
943 Data seg end, for brk()
944 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000945
fitzhardinge98abfc72003-12-16 02:05:15 +0000946static Addr do_brk(Addr newbrk)
njn25e49d8e72002-09-23 09:36:25 +0000947{
fitzhardinge98abfc72003-12-16 02:05:15 +0000948 Addr ret = VG_(brk_limit);
949 static const Bool debug = False;
950 Segment *seg;
951
952 if (debug)
953 VG_(printf)("do_brk: brk_base=%p brk_limit=%p newbrk=%p\n",
954 VG_(brk_base), VG_(brk_limit), newbrk);
955
956 if (newbrk < VG_(brk_base) || newbrk >= VG_(client_end))
957 return VG_(brk_limit);
958
959 /* brk isn't allowed to grow over anything else */
960 seg = VG_(find_segment)(VG_(brk_limit));
961
962 vg_assert(seg != NULL);
963
njn25e49d8e72002-09-23 09:36:25 +0000964 if (0)
fitzhardinge98abfc72003-12-16 02:05:15 +0000965 VG_(printf)("brk_limit=%p seg->addr=%p seg->end=%p\n",
966 VG_(brk_limit), seg->addr, seg->addr+seg->len);
967 vg_assert(VG_(brk_limit) >= seg->addr && VG_(brk_limit) <= (seg->addr + seg->len));
968
969 seg = VG_(next_segment)(seg);
970 if (seg != NULL && newbrk > seg->addr)
971 return VG_(brk_limit);
972
973 if (PGROUNDDN(newbrk) != PGROUNDDN(VG_(brk_limit))) {
974 Addr current = PGROUNDUP(VG_(brk_limit));
975 Addr newaddr = PGROUNDUP(newbrk);
976
977 /* new brk in a new page - fix the mappings */
978 if (newbrk > VG_(brk_limit)) {
979
980 if (debug)
981 VG_(printf)(" extending brk: current=%p newaddr=%p delta=%d\n",
982 current, newaddr, newaddr-current);
983
984 if (newaddr == current) {
985 ret = newbrk;
nethercoteb4250ae2004-07-10 16:50:09 +0000986 } else if ((void*)-1 != VG_(mmap)((void*)current, newaddr-current,
987 VKI_PROT_READ|VKI_PROT_WRITE|VKI_PROT_EXEC,
988 VKI_MAP_PRIVATE|VKI_MAP_ANONYMOUS|VKI_MAP_FIXED|VKI_MAP_CLIENT,
989 SF_FIXED|SF_BRK, -1, 0))
990 {
fitzhardinge98abfc72003-12-16 02:05:15 +0000991 ret = newbrk;
992 }
993 } else {
994 vg_assert(newbrk < VG_(brk_limit));
995
996 if (debug)
997 VG_(printf)(" shrinking brk: current=%p newaddr=%p delta=%d\n",
998 current, newaddr, current-newaddr);
999
1000 if (newaddr != current) {
nethercotee567e702004-07-10 17:49:17 +00001001 int res = VG_(munmap)((void *)newaddr, current - newaddr);
1002 vg_assert(0 == res);
fitzhardinge98abfc72003-12-16 02:05:15 +00001003 }
1004 ret = newbrk;
1005 }
1006 } else
1007 ret = newbrk;
1008
1009 VG_(brk_limit) = ret;
1010
1011 return ret;
1012}
1013
1014
njn25e49d8e72002-09-23 09:36:25 +00001015/* ---------------------------------------------------------------------
jsgf855d93d2003-10-13 22:26:55 +00001016 Vet file descriptors for sanity
1017 ------------------------------------------------------------------ */
1018
1019/* Return true if we're allowed to use or create this fd */
thughesad1c9562004-06-26 11:27:52 +00001020static Bool fd_allowed(Int fd, const Char *syscall, ThreadId tid, Bool soft)
jsgf855d93d2003-10-13 22:26:55 +00001021{
thughesad1c9562004-06-26 11:27:52 +00001022 if (fd < 0 || fd >= VG_(fd_hard_limit) || fd == VG_(clo_log_fd)) {
jsewardd9320a42003-12-12 06:40:05 +00001023 VG_(message)(Vg_UserMsg,
1024 "Warning: invalid file descriptor %d in syscall %s()",
1025 fd, syscall);
nethercotef8548672004-06-21 12:42:35 +00001026 if (fd == VG_(clo_log_fd))
jsewardd9320a42003-12-12 06:40:05 +00001027 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001028 " Use --log-fd=<number> to select an alternative log fd.");
jsgf855d93d2003-10-13 22:26:55 +00001029 if (VG_(clo_verbosity) > 1) {
1030 ExeContext *ec = VG_(get_ExeContext)(tid);
1031 VG_(pp_ExeContext)(ec);
1032 }
1033 return False;
1034 }
thughesad1c9562004-06-26 11:27:52 +00001035 else if (soft && fd >= VG_(fd_soft_limit)) {
1036 return False;
1037 }
jsgf855d93d2003-10-13 22:26:55 +00001038 return True;
1039}
1040
1041
1042/* ---------------------------------------------------------------------
njn25e49d8e72002-09-23 09:36:25 +00001043 The Main Entertainment ...
1044 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +00001045
thughesbaa46e52004-07-29 17:44:23 +00001046#define MayBlock (1 << 0)
1047#define PostOnFail (1 << 1)
jsgf855d93d2003-10-13 22:26:55 +00001048
1049#define PRE(x) \
1050 static void before_##x(ThreadId tid, ThreadState *tst)
1051#define POST(x) \
1052 static void after_##x(ThreadId tid, ThreadState *tst)
1053
jsgf855d93d2003-10-13 22:26:55 +00001054#define PREALIAS(new, old) \
1055 PRE(new) __attribute__((alias(STR(before_##old))))
1056#define POSTALIAS(new, old) \
1057 POST(new) __attribute__((alias(STR(after_##old))))
1058
1059#define SYSNO (tst->m_eax) /* in PRE(x) */
muellerb6c6acb2003-12-07 23:36:14 +00001060#define res (tst->m_eax) /* in POST(x) */
jsgf855d93d2003-10-13 22:26:55 +00001061#define arg1 (tst->m_ebx)
1062#define arg2 (tst->m_ecx)
1063#define arg3 (tst->m_edx)
1064#define arg4 (tst->m_esi)
1065#define arg5 (tst->m_edi)
1066#define arg6 (tst->m_ebp)
1067
1068PRE(exit_group)
1069{
1070 VG_(core_panic)("syscall exit_group() not caught by the scheduler?!");
1071}
1072
1073PRE(exit)
1074{
1075 VG_(core_panic)("syscall exit() not caught by the scheduler?!");
1076}
1077
jsgf855d93d2003-10-13 22:26:55 +00001078PRE(ptrace)
1079{
1080 /* long ptrace (enum __ptrace_request request, pid_t pid,
1081 void *addr, void *data); ... sort of. */
1082 /* Sigh ... the /usr/include/sys/user.h on R H 6.2 doesn't
1083 define struct user_fpxregs_struct. On the basis that it
1084 is defined as follows on my R H 7.2 (glibc-2.2.4) box,
1085 I kludge it.
1086
1087 struct user_fpxregs_struct
1088 {
1089 unsigned short int cwd;
1090 unsigned short int swd;
1091 unsigned short int twd;
1092 unsigned short int fop;
1093 long int fip;
1094 long int fcs;
1095 long int foo;
1096 long int fos;
1097 long int mxcsr;
1098 long int reserved;
1099 long int st_space[32]; 8*16 bytes for each FP-reg = 128 bytes
1100 long int xmm_space[32]; 8*16 bytes for each XMM-reg = 128 bytes
1101 long int padding[56];
1102 };
1103 */
1104 const Int sizeof_struct_user_fpxregs_struct
1105 = sizeof(unsigned short) * (1 + 1 + 1 + 1)
1106 + sizeof(long int) * (1 + 1 + 1 + 1 + 1 + 1 + 32 + 32 + 56);
1107
1108 MAYBE_PRINTF("ptrace ( %d, %d, %p, %p )\n", arg1,arg2,arg3,arg4);
1109 switch (arg1) {
1110 case 12: /* PTRACE_GETREGS */
1111 SYSCALL_TRACK( pre_mem_write, tid, "ptrace(getregs)", arg4,
1112 sizeof (struct user_regs_struct));
1113 break;
1114 case 14: /* PTRACE_GETFPREGS */
1115 SYSCALL_TRACK( pre_mem_write, tid, "ptrace(getfpregs)", arg4,
fitzhardinged65dcad2004-03-13 02:06:58 +00001116 sizeof (struct user_i387_struct));
jsgf855d93d2003-10-13 22:26:55 +00001117 break;
1118 case 18: /* PTRACE_GETFPXREGS */
1119 SYSCALL_TRACK( pre_mem_write, tid, "ptrace(getfpxregs)", arg4,
1120 sizeof_struct_user_fpxregs_struct);
1121 break;
1122 case 1: case 2: case 3: /* PTRACE_PEEK{TEXT,DATA,USER} */
1123 SYSCALL_TRACK( pre_mem_write, tid, "ptrace(peek)", arg4,
1124 sizeof (long));
1125 break;
1126 case 13: /* PTRACE_SETREGS */
1127 SYSCALL_TRACK( pre_mem_read, tid, "ptrace(setregs)", arg4,
1128 sizeof (struct user_regs_struct));
1129 break;
1130 case 15: /* PTRACE_SETFPREGS */
1131 SYSCALL_TRACK( pre_mem_read, tid, "ptrace(setfpregs)", arg4,
fitzhardinged65dcad2004-03-13 02:06:58 +00001132 sizeof (struct user_i387_struct));
jsgf855d93d2003-10-13 22:26:55 +00001133 break;
1134 case 19: /* PTRACE_SETFPXREGS */
1135 SYSCALL_TRACK( pre_mem_read, tid, "ptrace(setfpxregs)", arg4,
1136 sizeof_struct_user_fpxregs_struct);
1137 break;
1138 default:
1139 break;
1140 }
1141}
1142
1143POST(ptrace)
1144{
1145 const Int sizeof_struct_user_fpxregs_struct
1146 = sizeof(unsigned short) * (1 + 1 + 1 + 1)
1147 + sizeof(long int) * (1 + 1 + 1 + 1 + 1 + 1 + 32 + 32 + 56);
1148
1149 switch (arg1) {
1150 case 12: /* PTRACE_GETREGS */
1151 VG_TRACK( post_mem_write, arg4,
1152 sizeof (struct user_regs_struct));
1153 break;
1154 case 14: /* PTRACE_GETFPREGS */
1155 VG_TRACK( post_mem_write, arg4,
fitzhardinged65dcad2004-03-13 02:06:58 +00001156 sizeof (struct user_i387_struct));
jsgf855d93d2003-10-13 22:26:55 +00001157 break;
1158 case 18: /* PTRACE_GETFPXREGS */
1159 VG_TRACK( post_mem_write, arg4,
1160 sizeof_struct_user_fpxregs_struct);
1161 break;
1162 case 1: case 2: case 3: /* PTRACE_PEEK{TEXT,DATA,USER} */
1163 VG_TRACK( post_mem_write, arg4, sizeof (long));
1164 break;
1165 default:
1166 break;
1167 }
1168}
1169
1170PRE(mount)
1171{
1172 MAYBE_PRINTF( "mount( %p, %p, %p )\n" ,arg1,arg2,arg3);
1173 SYSCALL_TRACK( pre_mem_read_asciiz, tid,"mount(specialfile)",arg1);
1174 SYSCALL_TRACK( pre_mem_read_asciiz, tid,"mount(dir)",arg2);
1175 SYSCALL_TRACK( pre_mem_read_asciiz, tid,"mount(filesystemtype)",arg3);
1176}
1177
1178PRE(umount)
1179{
1180 /* int umount(const char *path) */
1181 MAYBE_PRINTF("umount( %p )\n", arg1);
1182 SYSCALL_TRACK( pre_mem_read_asciiz, tid,"umount(path)",arg1);
1183}
1184
1185PRE(modify_ldt)
1186{
1187 MAYBE_PRINTF("modify_ldt ( %d, %p, %d )\n", arg1,arg2,arg3);
1188 if (arg1 == 0) {
1189 /* read the LDT into ptr */
1190 SYSCALL_TRACK( pre_mem_write, tid,
1191 "modify_ldt(ptr)(func=0)", arg2, arg3 );
1192 }
1193 if (arg1 == 1 || arg1 == 0x11) {
1194 /* write the LDT with the entry pointed at by ptr */
1195 SYSCALL_TRACK( pre_mem_read, tid,
1196 "modify_ldt(ptr)(func=1 or 0x11)", arg2,
1197 sizeof(struct vki_modify_ldt_ldt_s) );
1198 }
1199 /* "do" the syscall ourselves; the kernel never sees it */
1200 res = VG_(sys_modify_ldt)( tid, arg1, (void*)arg2, arg3 );
1201
1202 if (arg1 == 0 && !VG_(is_kerror)(res) && res > 0) {
1203 VG_TRACK( post_mem_write, arg2, res );
1204 }
1205}
1206
fitzhardinge47735af2004-01-21 01:27:27 +00001207PRE(set_thread_area)
1208{
1209 MAYBE_PRINTF("set_thread_area ( %p )\n", arg1);
1210
1211 SYSCALL_TRACK( pre_mem_read, tid,
1212 "set_thread_area(ptr)", arg1,
1213 sizeof(struct vki_modify_ldt_ldt_s) );
1214
1215 /* "do" the syscall ourselves; the kernel never sees it */
1216 res = VG_(sys_set_thread_area)( tid, (void *)arg1 );
1217}
1218
1219PRE(get_thread_area)
1220{
1221 MAYBE_PRINTF("get_thread_area ( %p )\n", arg1);
1222 SYSCALL_TRACK( pre_mem_write, tid,
1223 "get_thread_area(ptr)", arg1,
1224 sizeof(struct vki_modify_ldt_ldt_s) );
1225
1226 /* "do" the syscall ourselves; the kernel never sees it */
1227 res = VG_(sys_get_thread_area)( tid, (void *)arg1 );
1228
1229 if (!VG_(is_kerror)(res)) {
1230 VG_TRACK( post_mem_write, arg1, sizeof(struct vki_modify_ldt_ldt_s) );
1231 }
1232}
1233
rjwalshcdf1cb52004-04-29 08:40:50 +00001234PRE(set_tid_address)
1235{
1236 MAYBE_PRINTF("set_tid_address ( %p )\n", arg1);
1237}
1238
jsgf855d93d2003-10-13 22:26:55 +00001239PRE(setresgid)
1240{
1241 /* int setresgid(gid_t rgid, gid_t egid, gid_t sgid); */
1242 MAYBE_PRINTF("setresgid ( %d, %d, %d )\n", arg1, arg2, arg3);
1243}
1244
1245PRE(vhangup)
1246{
1247 MAYBE_PRINTF("vhangup()\n");
1248}
1249
1250PRE(iopl)
1251{
1252 MAYBE_PRINTF("iopl ( %d )\n", arg1);
1253}
1254
1255PRE(setxattr)
1256{
1257 MAYBE_PRINTF("setxattr ( %p, %p, %p, %d, %d )\n",
1258 arg1, arg2, arg3, arg4, arg5);
1259 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "setxattr(path)", arg1 );
1260 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "setxattr(name)", arg2 );
1261 SYSCALL_TRACK( pre_mem_read, tid, "setxattr(value)", arg3, arg4 );
1262}
1263
1264PREALIAS(lsetxattr, setxattr);
1265
1266PRE(fsetxattr)
1267{
1268 /* int fsetxattr (int filedes, const char *name,
1269 const void *value, size_t size, int flags); */
1270 MAYBE_PRINTF("fsetxattr ( %d, %p, %p, %d, %d )\n",
1271 arg1, arg2, arg3, arg4, arg5);
1272 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "fsetxattr(name)", arg2 );
1273 SYSCALL_TRACK( pre_mem_read, tid, "fsetxattr(value)", arg3, arg4 );
1274}
1275
1276PRE(getxattr)
1277{
1278 MAYBE_PRINTF("getxattr ( %p, %p, %p, %d )\n",
1279 arg1,arg2,arg3, arg4);
1280 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "getxattr(path)", arg1 );
1281 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "getxattr(name)", arg2 );
1282 SYSCALL_TRACK( pre_mem_write, tid, "getxattr(value)", arg3, arg4 );
1283}
1284
1285POST(getxattr)
1286{
1287 if (res > 0 && arg3 != (Addr)NULL) {
1288 VG_TRACK( post_mem_write, arg3, res );
1289 }
1290}
1291
1292PREALIAS(lgetxattr, getxattr);
1293POSTALIAS(lgetxattr, getxattr);
1294
1295PRE(fgetxattr)
1296{
1297 MAYBE_PRINTF("fgetxattr ( %d, %p, %p, %d )\n",
1298 arg1, arg2, arg3, arg4);
1299 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "fgetxattr(name)", arg2 );
1300 SYSCALL_TRACK( pre_mem_write, tid, "fgetxattr(value)", arg3, arg4 );
1301}
1302
1303POST(fgetxattr)
1304{
1305 if (res > 0 && arg3 != (Addr)NULL)
1306 VG_TRACK( post_mem_write, arg3, res );
1307}
1308
1309PRE(listxattr)
1310{
1311 MAYBE_PRINTF("listxattr ( %p, %p, %d )\n", arg1, arg2, arg3);
1312 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "listxattr(path)", arg1 );
1313 SYSCALL_TRACK( pre_mem_write, tid, "listxattr(list)", arg2, arg3 );
1314}
1315
1316POST(listxattr)
1317{
1318 if (res > 0 && arg2 != (Addr)NULL)
1319 VG_TRACK( post_mem_write, arg2, res );
1320}
1321
1322PREALIAS(llistxattr, listxattr);
1323POSTALIAS(llistxattr, listxattr);
1324
1325PRE(flistxattr)
1326{
1327 /* ssize_t flistxattr (int filedes, char *list, size_t size); */
1328 MAYBE_PRINTF("flistxattr ( %d, %p, %d )\n", arg1, arg2, arg3);
1329 SYSCALL_TRACK( pre_mem_write, tid, "listxattr(list)", arg2, arg3 );
1330}
1331
1332POST(flistxattr)
1333{
1334 if (res > 0 && arg2 != (Addr)NULL)
1335 VG_TRACK( post_mem_write, arg2, res );
1336}
1337
1338PRE(removexattr)
1339{
1340 MAYBE_PRINTF("removexattr ( %p, %p )\n", arg1, arg2);
1341 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "listxattr(path)", arg1 );
1342 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "listxattr(name)", arg2 );
1343}
1344
1345PREALIAS(lremovexattr, removexattr);
1346
1347PRE(fremovexattr)
1348{
1349 MAYBE_PRINTF("removexattr ( %d, %p )\n", arg1, arg2);
1350 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "listxattr(name)", arg2 );
1351}
1352
1353PRE(quotactl)
1354{
1355 MAYBE_PRINTF("quotactl (0x%x, %p, 0x%x, 0x%x )\n",
1356 arg1,arg2,arg3, arg4);
1357 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "quotactl(special)", arg2 );
1358}
1359
1360PRE(lookup_dcookie)
1361{
1362 MAYBE_PRINTF("lookup_dcookie (0x%llx, %p, %d)\n",
1363 arg1 | ((long long) arg2 << 32), arg3, arg4);
1364 SYSCALL_TRACK( pre_mem_write, tid, "lookup_dcookie(buf)", arg3, arg4);
1365}
1366
1367POST(lookup_dcookie)
1368{
1369 if (arg3 != (Addr)NULL)
1370 VG_TRACK( post_mem_write, arg3, res);
1371}
1372
1373PRE(truncate64)
1374{
1375 MAYBE_PRINTF("truncate64 ( %p, %lld )\n",
1376 arg1, ((ULong)arg2) | (((ULong) arg3) << 32));
1377 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "truncate64(path)", arg1 );
1378}
1379
1380PRE(fdatasync)
1381{
1382 /* int fdatasync(int fd); */
1383 MAYBE_PRINTF("fdatasync ( %d )\n", arg1);
1384}
1385
1386PRE(msync)
1387{
1388 /* int msync(const void *start, size_t length, int flags); */
1389 MAYBE_PRINTF("msync ( %p, %d, %d )\n", arg1,arg2,arg3);
1390 SYSCALL_TRACK( pre_mem_read, tid, "msync(start)", arg1, arg2 );
1391}
1392
1393struct getpmsg_strbuf {
1394 int maxlen; /* no. of bytes in buffer */
1395 int len; /* no. of bytes returned */
1396 caddr_t buf; /* pointer to data */
1397};
1398
1399PRE(getpmsg)
1400{
1401 /* LiS getpmsg from http://www.gcom.com/home/linux/lis/ */
1402 /* int getpmsg(int fd, struct strbuf *ctrl, struct strbuf *data,
1403 int *bandp, int *flagsp); */
1404 struct getpmsg_strbuf *ctrl;
1405 struct getpmsg_strbuf *data;
1406 MAYBE_PRINTF("getpmsg ( %d, %p, %p, %p, %p )\n",
1407 arg1,arg2,arg3,arg4,arg5);
1408 ctrl = (struct getpmsg_strbuf *)arg2;
1409 data = (struct getpmsg_strbuf *)arg3;
1410 if (ctrl && ctrl->maxlen > 0)
1411 SYSCALL_TRACK( pre_mem_write,tid, "getpmsg(ctrl)",
1412 (UInt)ctrl->buf, ctrl->maxlen);
1413 if (data && data->maxlen > 0)
1414 SYSCALL_TRACK( pre_mem_write,tid, "getpmsg(data)",
1415 (UInt)data->buf, data->maxlen);
1416 if (arg4)
1417 SYSCALL_TRACK( pre_mem_write,tid, "getpmsg(bandp)",
1418 (UInt)arg4, sizeof(int));
1419 if (arg5)
1420 SYSCALL_TRACK( pre_mem_write,tid, "getpmsg(flagsp)",
1421 (UInt)arg5, sizeof(int));
1422}
1423
1424POST(getpmsg)
1425{
1426 struct getpmsg_strbuf *ctrl;
1427 struct getpmsg_strbuf *data;
1428
1429 ctrl = (struct getpmsg_strbuf *)arg2;
1430 data = (struct getpmsg_strbuf *)arg3;
1431 if (res == 0 && ctrl && ctrl->len > 0) {
1432 VG_TRACK( post_mem_write, (UInt)ctrl->buf, ctrl->len);
1433 }
1434 if (res == 0 && data && data->len > 0) {
1435 VG_TRACK( post_mem_write, (UInt)data->buf, data->len);
1436 }
1437}
1438
1439PRE(putpmsg)
1440{
1441 /* LiS putpmsg from http://www.gcom.com/home/linux/lis/ */
1442 /* int putpmsg(int fd, struct strbuf *ctrl, struct strbuf *data,
1443 int band, int flags); */
1444 struct strbuf {
1445 int maxlen; /* no. of bytes in buffer */
1446 int len; /* no. of bytes returned */
1447 caddr_t buf; /* pointer to data */
1448 };
1449 struct strbuf *ctrl;
1450 struct strbuf *data;
1451 MAYBE_PRINTF("putpmsg ( %d, %p, %p, %d, %d )\n",
1452 arg1,arg2,arg3,arg4,arg5);
1453 ctrl = (struct strbuf *)arg2;
1454 data = (struct strbuf *)arg3;
1455 if (ctrl && ctrl->len > 0)
1456 SYSCALL_TRACK( pre_mem_read,tid, "putpmsg(ctrl)",
1457 (UInt)ctrl->buf, ctrl->len);
1458 if (data && data->len > 0)
1459 SYSCALL_TRACK( pre_mem_read,tid, "putpmsg(data)",
1460 (UInt)data->buf, data->len);
1461}
1462
1463PRE(getitimer)
1464{
1465 /* int getitimer(int which, struct itimerval *value); */
1466 MAYBE_PRINTF("getitimer ( %d, %p )\n", arg1, arg2);
1467 SYSCALL_TRACK( pre_mem_write, tid, "getitimer(timer)", arg2,
1468 sizeof(struct itimerval) );
1469}
1470
1471POST(getitimer)
1472{
1473 if (arg2 != (Addr)NULL) {
1474 VG_TRACK( post_mem_write,arg2, sizeof(struct itimerval));
1475 }
1476}
1477
1478PRE(syslog)
1479{
1480 /* int syslog(int type, char *bufp, int len); */
1481 MAYBE_PRINTF("syslog (%d, %p, %d)\n",arg1,arg2,arg3);
1482 switch(arg1) {
1483 case 2: case 3: case 4:
1484 SYSCALL_TRACK( pre_mem_write, tid, "syslog(buf)", arg2, arg3);
1485 break;
1486 default:
1487 break;
1488 }
1489}
1490
1491POST(syslog)
1492{
1493 switch (arg1) {
1494 case 2: case 3: case 4:
1495 VG_TRACK( post_mem_write, arg2, arg3 );
1496 break;
1497 default:
1498 break;
1499 }
1500}
1501
1502PRE(personality)
1503{
1504 /* int personality(unsigned long persona); */
1505 MAYBE_PRINTF("personality ( %d )\n", arg1);
1506}
1507
1508PRE(chroot)
1509{
1510 /* int chroot(const char *path); */
1511 MAYBE_PRINTF("chroot ( %p )\n", arg1);
1512 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "chroot(path)", arg1 );
1513}
1514
1515PRE(madvise)
1516{
1517 /* int madvise(void *start, size_t length, int advice ); */
1518 MAYBE_PRINTF("madvise ( %p, %d, %d )\n", arg1,arg2,arg3);
1519}
1520
1521PRE(mremap)
1522{
nethercote27ea8bc2004-07-10 17:21:14 +00001523 // Nb: this is different to the glibc version described in the man pages,
1524 // which lacks the fifth 'new_address' argument.
jsgf855d93d2003-10-13 22:26:55 +00001525 /* void* mremap(void * old_address, size_t old_size,
fitzhardinge1a303042003-12-22 08:48:50 +00001526 size_t new_size, unsigned long flags, void * new_address); */
1527 MAYBE_PRINTF("mremap ( %p, %d, %d, 0x%x, %p )\n",
1528 arg1, arg2, arg3, arg4, arg5);
nethercote27ea8bc2004-07-10 17:21:14 +00001529
fitzhardinge1a303042003-12-22 08:48:50 +00001530 res = mremap_segment((Addr)arg1, arg2, (Addr)arg5, arg3, arg4, tid);
jsgf855d93d2003-10-13 22:26:55 +00001531}
1532
1533PRE(nice)
1534{
1535 /* int nice(int inc); */
1536 MAYBE_PRINTF("nice ( %d )\n", arg1);
1537}
1538
1539PRE(setresgid32)
1540{
1541 /* int setresgid(gid_t rgid, gid_t egid, gid_t sgid); */
1542 MAYBE_PRINTF("setresgid32 ( %d, %d, %d )\n", arg1, arg2, arg3);
1543}
1544
1545PRE(setfsuid32)
1546{
1547 /* int setfsuid(uid_t fsuid); */
1548 MAYBE_PRINTF("setfsuid ( %d )\n", arg1);
1549}
1550
1551PRE(_sysctl)
1552{
1553 /* int _sysctl(struct __sysctl_args *args); */
1554 MAYBE_PRINTF("_sysctl ( %p )\n", arg1 );
1555 SYSCALL_TRACK( pre_mem_write, tid, "_sysctl(args)", arg1,
1556 sizeof(struct __sysctl_args) );
1557}
1558
1559POST(_sysctl)
1560{
1561 VG_TRACK( post_mem_write, arg1, sizeof(struct __sysctl_args) );
1562
1563}
1564
1565PRE(sched_getscheduler)
1566{
1567 /* int sched_getscheduler(pid_t pid); */
1568 MAYBE_PRINTF("sched_getscheduler ( %d )\n", arg1);
1569}
1570
1571PRE(sched_setscheduler)
1572{
1573 /* int sched_setscheduler(pid_t pid, int policy,
1574 const struct sched_param *p); */
1575 MAYBE_PRINTF("sched_setscheduler ( %d, %d, %p )\n",arg1,arg2,arg3);
1576 if (arg3 != (UInt)NULL)
1577 SYSCALL_TRACK( pre_mem_read, tid,
1578 "sched_setscheduler(struct sched_param *p)",
1579 arg3, sizeof(struct sched_param));
1580}
1581
1582PRE(mlock)
1583{
1584 /* int mlock(const void * addr, size_t len) */
1585 MAYBE_PRINTF("mlock ( %p, %d )\n", arg1, arg2);
1586}
1587
1588PRE(munlock)
1589{
1590 /* int munlock(const void * addr, size_t len) */
1591 MAYBE_PRINTF("munlock ( %p, %d )\n", arg1, arg2);
1592}
1593
1594PRE(mlockall)
1595{
1596 /* int mlockall(int flags); */
1597 MAYBE_PRINTF("mlockall ( %x )\n", arg1);
1598}
1599
1600PRE(munlockall)
1601{
1602 /* int munlock(const void * addr, size_t len) */
1603 MAYBE_PRINTF("munlock ( %p, %d )\n", arg1, arg2);
1604}
1605
1606PRE(sched_get_priority_max)
1607{
1608 /* int sched_get_priority_max(int policy); */
1609 MAYBE_PRINTF("sched_get_priority_max ( %d )\n", arg1);
1610}
1611
1612PRE(sched_get_priority_min)
1613{
1614 /* int sched_get_priority_min(int policy); */
1615 MAYBE_PRINTF("sched_get_priority_min ( %d )\n", arg1);
1616}
1617
1618PRE(setpriority)
1619{
1620 /* int setpriority(int which, int who, int prio); */
1621 MAYBE_PRINTF("setpriority ( %d, %d, %d )\n", arg1, arg2, arg3);
1622}
1623
1624PRE(getpriority)
1625{
1626 /* int getpriority(int which, int who); */
1627 MAYBE_PRINTF("getpriority ( %d, %d )\n", arg1, arg2);
1628}
1629
1630PRE(setfsgid)
1631{
1632 /* int setfsgid(gid_t gid); */
1633 MAYBE_PRINTF("setfsgid ( %d )\n", arg1);
1634}
1635
1636PRE(setregid)
1637{
1638 /* int setregid(gid_t rgid, gid_t egid); */
1639 MAYBE_PRINTF("setregid ( %d, %d )\n", arg1, arg2);
1640}
1641
1642PRE(setresuid)
1643{
1644 /* int setresuid(uid_t ruid, uid_t euid, uid_t suid); */
1645 MAYBE_PRINTF("setresuid ( %d, %d, %d )\n", arg1, arg2, arg3);
1646}
1647
1648PRE(setfsuid)
1649{
1650 /* int setfsuid(uid_t uid); */
1651 MAYBE_PRINTF("setfsuid ( %d )\n", arg1);
1652}
1653
1654PRE(sendfile)
1655{
1656 /* ssize_t sendfile(int out_fd, int in_fd, off_t *offset,
1657 size_t count) */
1658 MAYBE_PRINTF("sendfile ( %d, %d, %p, %d )\n",arg1,arg2,arg3,arg4);
1659 if (arg3 != (UInt)NULL)
1660 SYSCALL_TRACK( pre_mem_write, tid, "sendfile(offset)",
1661 arg3, sizeof(off_t) );
1662}
1663
1664POST(sendfile)
1665{
1666 VG_TRACK( post_mem_write, arg3, sizeof( off_t ) );
1667}
1668
1669PRE(sendfile64)
1670{
1671 /* ssize_t sendfile64(int out_df, int in_fd, loff_t *offset,
1672 size_t count); */
1673 MAYBE_PRINTF("sendfile64 ( %d, %d, %p, %d )\n",arg1,arg2,arg3,arg4);
1674 if (arg3 != (UInt)NULL)
1675 SYSCALL_TRACK( pre_mem_write, tid, "sendfile64(offset)",
1676 arg3, sizeof(loff_t) );
1677}
1678
1679POST(sendfile64)
1680{
1681 if (arg3 != (UInt)NULL ) {
1682 VG_TRACK( post_mem_write, arg3, sizeof(loff_t) );
1683 }
1684}
1685
1686PRE(pwrite64)
1687{
1688 /* ssize_t pwrite (int fd, const void *buf, size_t nbytes,
1689 off_t offset); */
1690 MAYBE_PRINTF("pwrite64 ( %d, %p, %d, %d )\n", arg1, arg2, arg3, arg4);
1691 SYSCALL_TRACK( pre_mem_read, tid, "pwrite(buf)", arg2, arg3 );
1692}
1693
1694PRE(sync)
1695{
1696 /* int sync(); */
1697 MAYBE_PRINTF("sync ( )\n");
1698}
1699
1700PRE(fstatfs)
1701{
1702 /* int fstatfs(int fd, struct statfs *buf); */
1703 MAYBE_PRINTF("fstatfs ( %d, %p )\n",arg1,arg2);
1704 SYSCALL_TRACK( pre_mem_write, tid, "stat(buf)",
thughes66d80092004-06-19 12:41:05 +00001705 arg2, sizeof(struct vki_statfs) );
jsgf855d93d2003-10-13 22:26:55 +00001706}
1707
1708POST(fstatfs)
1709{
thughes66d80092004-06-19 12:41:05 +00001710 VG_TRACK( post_mem_write, arg2, sizeof(struct vki_statfs) );
jsgf855d93d2003-10-13 22:26:55 +00001711}
1712
1713PRE(getsid)
1714{
1715 /* pid_t getsid(pid_t pid); */
1716 MAYBE_PRINTF("getsid ( %d )\n", arg1);
1717}
1718
1719PRE(pread64)
1720{
1721 /* ssize_t pread64(int fd, void *buf, size_t count, off_t offset); */
1722 MAYBE_PRINTF("pread ( %d, %p, %d, %d ) ...\n",arg1,arg2,arg3,arg4);
1723 SYSCALL_TRACK( pre_mem_write, tid, "pread(buf)", arg2, arg3 );
1724}
1725
1726POST(pread64)
1727{
1728 MAYBE_PRINTF("SYSCALL[%d] pread ( %d, %p, %d, %d ) --> %d\n",
1729 VG_(getpid)(),
1730 arg1, arg2, arg3, arg4, res);
1731 if (res > 0) {
1732 VG_TRACK( post_mem_write, arg2, res );
1733 }
1734}
1735
1736PRE(mknod)
1737{
1738 /* int mknod(const char *pathname, mode_t mode, dev_t dev); */
1739 MAYBE_PRINTF("mknod ( %p, 0x%x, 0x%x )\n", arg1, arg2, arg3 );
1740 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "mknod(pathname)", arg1 );
1741}
1742
1743PRE(flock)
1744{
1745 /* int flock(int fd, int operation); */
1746 MAYBE_PRINTF("flock ( %d, %d )\n", arg1, arg2 );
1747}
1748
1749PRE(init_module)
1750{
1751 /* int init_module(const char *name, struct module *image); */
1752 MAYBE_PRINTF("init_module ( %p, %p )\n", arg1, arg2 );
1753 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "init_module(name)", arg1 );
1754 SYSCALL_TRACK( pre_mem_read, tid, "init_module(image)", arg2,
1755 VKI_SIZEOF_STRUCT_MODULE );
1756}
1757
1758PRE(ioperm)
1759{
1760 /* int ioperm(unsigned long from, unsigned long num, int turn_on); */
1761 MAYBE_PRINTF("ioperm ( %d, %d, %d )\n", arg1, arg2, arg3 );
1762}
1763
1764PRE(capget)
1765{
1766 /* int capget(cap_user_header_t header, cap_user_data_t data); */
1767 MAYBE_PRINTF("capget ( %p, %p )\n", arg1, arg2 );
1768 SYSCALL_TRACK( pre_mem_read, tid, "capget(header)", arg1,
1769 sizeof(vki_cap_user_header_t) );
1770 SYSCALL_TRACK( pre_mem_write, tid, "capget(data)", arg2,
1771 sizeof( vki_cap_user_data_t) );
1772}
1773
1774POST(capget)
1775{
1776 if (arg2 != (Addr)NULL)
1777 VG_TRACK( post_mem_write, arg2, sizeof( vki_cap_user_data_t) );
1778}
1779
1780PRE(capset)
1781{
1782 SYSCALL_TRACK( pre_mem_read, tid, "capset(header)",
1783 arg1, sizeof(vki_cap_user_header_t) );
1784 SYSCALL_TRACK( pre_mem_read, tid, "capset(data)",
1785 arg2, sizeof( vki_cap_user_data_t) );
1786}
1787
nethercotea81e9162004-02-12 14:34:14 +00001788// Pre_read a char** argument.
1789void pre_argv_envp(Addr a, ThreadId tid, Char* s1, Char* s2)
1790{
1791 while (True) {
1792 Addr a_deref = deref_Addr( tid, a, s1 );
1793 if (0 == a_deref)
1794 break;
1795 SYSCALL_TRACK( pre_mem_read_asciiz, tid, s2, a_deref );
1796 a += sizeof(char*);
1797 }
1798}
1799
jsgf855d93d2003-10-13 22:26:55 +00001800PRE(execve)
1801{
1802 /* int execve (const char *filename,
1803 char *const argv [],
1804 char *const envp[]); */
nethercotea81e9162004-02-12 14:34:14 +00001805 MAYBE_PRINTF("execve ( %p(%s), %p, %p )\n", arg1, arg1, arg2, arg3);
1806
1807 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "execve(filename)", arg1 );
thughes7f72d012004-07-21 16:23:38 +00001808 if (arg2 != (UInt)NULL)
1809 pre_argv_envp( arg2, tid, "execve(argv)", "execve(argv[i])" );
thughes4b9e0152004-06-19 13:02:34 +00001810 if (arg3 != (UInt)NULL)
1811 pre_argv_envp( arg3, tid, "execve(envp)", "execve(envp[i])" );
fitzhardingee1c06d82003-10-30 07:21:44 +00001812
1813 /* Erk. If the exec fails, then the following will have made a
1814 mess of things which makes it hard for us to continue. The
1815 right thing to do is piece everything together again in
1816 POST(execve), but that's hard work. Instead, we make an effort
1817 to check that the execve will work before actually calling
1818 exec. */
1819 {
1820 struct vki_stat st;
1821 Int ret = VG_(stat)((Char *)arg1, &st);
1822
1823 if (ret < 0) {
1824 res = ret;
1825 return;
1826 }
1827 /* just look for any X bit set
1828 XXX do proper permissions check?
1829 */
1830 if ((st.st_mode & 0111) == 0) {
1831 res = -VKI_EACCES;
1832 return;
1833 }
1834 }
1835
1836 /* Resistance is futile. Nuke all other threads. POSIX mandates
1837 this. (Really, nuke them all, since the new process will make
1838 its own new thread.) */
1839 VG_(nuke_all_threads_except)( VG_INVALID_THREADID );
1840
fitzhardinge5408c062004-01-04 23:52:59 +00001841 {
fitzhardinge98abfc72003-12-16 02:05:15 +00001842 /* Make the LD_LIBRARY_PATH/LD_PRELOAD disappear so that the
fitzhardinge5408c062004-01-04 23:52:59 +00001843 child doesn't get our libpthread and other stuff. This is
1844 done unconditionally, since if we are tracing the child,
1845 stage1/2 will set up the appropriate client environment. */
jsgf855d93d2003-10-13 22:26:55 +00001846 Int i;
1847 Char** envp = (Char**)arg3;
1848 Char* ld_preload_str = NULL;
1849 Char* ld_library_path_str = NULL;
fitzhardinge98abfc72003-12-16 02:05:15 +00001850
1851 if (envp != NULL) {
1852 Char *buf;
1853
1854 for (i = 0; envp[i] != NULL; i++) {
1855 if (VG_(strncmp)(envp[i], "LD_PRELOAD=", 11) == 0)
1856 ld_preload_str = &envp[i][11];
1857 if (VG_(strncmp)(envp[i], "LD_LIBRARY_PATH=", 16) == 0)
1858 ld_library_path_str = &envp[i][16];
1859 }
1860
1861 buf = VG_(arena_malloc)(VG_AR_CORE, VG_(strlen)(VG_(libdir)) + 20);
1862
nethercoteff9721d2004-01-26 17:10:01 +00001863 VG_(sprintf)(buf, "%s*/vg_inject.so", VG_(libdir));
1864 VG_(mash_colon_env)(ld_preload_str, buf);
fitzhardinge98abfc72003-12-16 02:05:15 +00001865
nethercoteff9721d2004-01-26 17:10:01 +00001866 VG_(sprintf)(buf, "%s*/vgpreload_*.so", VG_(libdir));
1867 VG_(mash_colon_env)(ld_preload_str, buf);
fitzhardingef8b559d2003-12-19 00:35:20 +00001868
nethercoteff9721d2004-01-26 17:10:01 +00001869 VG_(sprintf)(buf, "%s*", VG_(libdir));
1870 VG_(mash_colon_env)(ld_library_path_str, buf);
fitzhardinge98abfc72003-12-16 02:05:15 +00001871
nethercoteff9721d2004-01-26 17:10:01 +00001872 VG_(env_unsetenv)(envp, VALGRINDCLO);
fitzhardinge98abfc72003-12-16 02:05:15 +00001873
1874 /* XXX if variable becomes empty, remove it completely? */
jsgf855d93d2003-10-13 22:26:55 +00001875 }
fitzhardinge5408c062004-01-04 23:52:59 +00001876 }
1877
1878 if (VG_(clo_trace_children)) {
fitzhardinge98abfc72003-12-16 02:05:15 +00001879 /* If we're tracing the children, then we need to start it
1880 with our starter+arguments.
1881 */
1882 Int i;
1883 Char *exec = (Char *)arg1;
1884 Char **env = (Char **)arg3;
1885 Char *cp;
1886 Char *exename;
1887 Bool sawexec = False;
1888 Char *optvar;
1889 Int optlen;
1890
1891 optlen = 1;
1892 for(i = 0; i < VG_(vg_argc); i++)
1893 optlen += VG_(strlen)(VG_(vg_argv)[i]) + 1;
1894
1895 /* All these are leaked - we're either going to exec, or panic
1896 when we fail. */
1897 exename = VG_(arena_malloc)(VG_AR_CORE, 64);
1898 exec = VG_(arena_malloc)(VG_AR_CORE, VG_(strlen)(exec) + 7 /* --exec= */ + 1 /* \0 */);
1899
1900 VG_(sprintf)(exec, "--exec=%s", (Char *)arg1);
fitzhardingea49f9b52003-12-16 22:26:45 +00001901 VG_(sprintf)(exename, "/proc/self/fd/%d", VG_(vgexecfd));
fitzhardinge98abfc72003-12-16 02:05:15 +00001902
1903 optlen += VG_(strlen)(exec)+1;
1904
1905 optvar = VG_(arena_malloc)(VG_AR_CORE, optlen);
1906
1907 /* valgrind arguments */
1908 cp = optvar;
1909
1910 for(i = 1; i < VG_(vg_argc); i++) {
1911 Char *arg = VG_(vg_argv)[i];
1912 Int len;
1913
1914 if (VG_(memcmp)(arg, "--exec=", 7) == 0) {
1915 /* replace existing --exec= arg */
1916 sawexec = True;
1917 arg = exec;
1918 } else if (VG_(strcmp)(VG_(vg_argv)[i], "--") == 0)
1919 break;
1920
1921 len = VG_(strlen)(arg);
1922 VG_(memcpy)(cp, arg, len);
1923 cp += len;
1924 *cp++ = '\01';
1925 }
1926
1927 if (!sawexec) {
1928 Int execlen = VG_(strlen)(exec);
1929 VG_(memcpy)(cp, exec, execlen);
1930 cp += execlen;
1931 *cp++ = '\01';
1932 }
1933 *cp = '\0';
1934
1935 VG_(env_setenv)(&env, VALGRINDCLO, optvar);
1936
1937 arg1 = (UInt)exename;
1938 arg3 = (UInt)env;
1939 }
1940
1941 if (0) {
1942 Char **cpp;
1943
1944 VG_(printf)("exec: %s\n", (Char *)arg1);
1945 for(cpp = (Char **)arg2; cpp && *cpp; cpp++)
1946 VG_(printf)("argv: %s\n", *cpp);
1947 for(cpp = (Char **)arg3; cpp && *cpp; cpp++)
1948 VG_(printf)("env: %s\n", *cpp);
jsgf855d93d2003-10-13 22:26:55 +00001949 }
jsgf855d93d2003-10-13 22:26:55 +00001950
fitzhardingef0dd7e12004-01-16 02:17:30 +00001951 /* Set our real sigmask to match the client's sigmask so that the
1952 exec'd child will get the right mask. First we need to clear
1953 out any pending signals so they they don't get delivered, which
1954 would confuse things.
1955
1956 XXX This is a bug - the signals should remain pending, and be
1957 delivered to the new process after exec. There's also a
1958 race-condition, since if someone delivers us a signal between
1959 the sigprocmask and the execve, we'll still get the signal. Oh
1960 well.
1961 */
1962 {
1963 vki_ksigset_t allsigs;
1964 vki_ksiginfo_t info;
1965 static const struct vki_timespec zero = { 0, 0 };
1966
1967 VG_(ksigfillset)(&allsigs);
1968 while(VG_(ksigtimedwait)(&allsigs, &info, &zero) > 0)
1969 ;
1970
1971 VG_(ksigprocmask)(VKI_SIG_SETMASK, &tst->sig_mask, NULL);
1972 }
1973
fitzhardingeb50068f2004-02-24 23:42:55 +00001974 /* restore the DATA rlimit for the child */
1975 VG_(setrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
1976
fitzhardingee1c06d82003-10-30 07:21:44 +00001977 res = VG_(do_syscall)(__NR_execve, arg1, arg2, arg3);
1978
1979 /* If we got here, then the execve failed. We've already made too much of a mess
1980 of ourselves to continue, so we have to abort. */
1981 VG_(message)(Vg_UserMsg, "execve(%p \"%s\", %p, %p) failed, errno %d",
1982 arg1, arg1, arg2, arg3, -res);
1983 VG_(core_panic)("EXEC FAILED: I can't recover from execve() failing, so I'm dying.\n"
1984 "Add more stringent tests in PRE(execve), or work out how to recover.");
jsgf855d93d2003-10-13 22:26:55 +00001985}
1986
1987PRE(access)
1988{
1989 /* int access(const char *pathname, int mode); */
1990 MAYBE_PRINTF("access ( %p, %d )\n", arg1,arg2);
1991 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "access(pathname)", arg1 );
1992}
1993
1994PRE(alarm)
1995{
1996 /* unsigned int alarm(unsigned int seconds); */
1997 MAYBE_PRINTF("alarm ( %d )\n", arg1);
1998}
1999
2000PRE(brk)
2001{
fitzhardinge98abfc72003-12-16 02:05:15 +00002002 Addr brk_limit = VG_(brk_limit);
2003
jsgf855d93d2003-10-13 22:26:55 +00002004 /* libc says: int brk(void *end_data_segment);
2005 kernel says: void* brk(void* end_data_segment); (more or less)
2006
2007 libc returns 0 on success, and -1 (and sets errno) on failure.
2008 Nb: if you ask to shrink the dataseg end below what it
2009 currently is, that always succeeds, even if the dataseg end
2010 doesn't actually change (eg. brk(0)). Unless it seg faults.
2011
2012 Kernel returns the new dataseg end. If the brk() failed, this
2013 will be unchanged from the old one. That's why calling (kernel)
2014 brk(0) gives the current dataseg end (libc brk() just returns
2015 zero in that case).
2016
2017 Both will seg fault if you shrink it back into a text segment.
2018 */
2019 MAYBE_PRINTF("brk ( %p ) --> ",arg1);
jsgf855d93d2003-10-13 22:26:55 +00002020
fitzhardinge98abfc72003-12-16 02:05:15 +00002021 res = do_brk(arg1);
2022
jsgf855d93d2003-10-13 22:26:55 +00002023 MAYBE_PRINTF("0x%x\n", res);
2024
2025 if (res == arg1) {
2026 /* brk() succeeded */
fitzhardinge98abfc72003-12-16 02:05:15 +00002027 if (res < brk_limit) {
jsgf855d93d2003-10-13 22:26:55 +00002028 /* successfully shrunk the data segment. */
2029 VG_TRACK( die_mem_brk, (Addr)arg1,
fitzhardinge98abfc72003-12-16 02:05:15 +00002030 brk_limit-arg1 );
jsgf855d93d2003-10-13 22:26:55 +00002031 } else
fitzhardinge98abfc72003-12-16 02:05:15 +00002032 if (res > brk_limit) {
jsgf855d93d2003-10-13 22:26:55 +00002033 /* successfully grew the data segment */
fitzhardinge98abfc72003-12-16 02:05:15 +00002034 VG_TRACK( new_mem_brk, brk_limit,
2035 arg1-brk_limit );
jsgf855d93d2003-10-13 22:26:55 +00002036 }
jsgf855d93d2003-10-13 22:26:55 +00002037 } else {
2038 /* brk() failed */
fitzhardinge98abfc72003-12-16 02:05:15 +00002039 vg_assert(brk_limit == res);
jsgf855d93d2003-10-13 22:26:55 +00002040 }
2041}
2042
2043PRE(chdir)
2044{
2045 /* int chdir(const char *path); */
2046 MAYBE_PRINTF("chdir ( %p )\n", arg1);
2047 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "chdir(path)", arg1 );
2048}
2049
2050PRE(chmod)
2051{
2052 /* int chmod(const char *path, mode_t mode); */
2053 MAYBE_PRINTF("chmod ( %p, %d )\n", arg1,arg2);
2054 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "chmod(path)", arg1 );
2055}
2056
2057PRE(chown)
2058{
2059 /* int chown(const char *path, uid_t owner, gid_t group); */
2060 MAYBE_PRINTF("chown ( %p, 0x%x, 0x%x )\n", arg1,arg2,arg3);
2061 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "chown(path)", arg1 );
2062}
2063
2064PREALIAS(chown32, chown);
2065PREALIAS(lchown32, chown);
2066
2067PRE(close)
2068{
2069 /* int close(int fd); */
2070 MAYBE_PRINTF("close ( %d )\n",arg1);
nethercotef8548672004-06-21 12:42:35 +00002071 /* Detect and negate attempts by the client to close Valgrind's log fd */
thughesad1c9562004-06-26 11:27:52 +00002072 if (!fd_allowed(arg1, "close", tid, False))
jsgf855d93d2003-10-13 22:26:55 +00002073 res = -VKI_EBADF;
2074}
2075
rjwalshf5f536f2003-11-17 17:45:00 +00002076POST(close)
2077{
2078 if(VG_(clo_track_fds)) record_fd_close(tid, arg1);
2079}
jsgf855d93d2003-10-13 22:26:55 +00002080
2081PRE(dup)
2082{
2083 /* int dup(int oldfd); */
2084 MAYBE_PRINTF("dup ( %d ) --> ", arg1);
2085}
2086
2087POST(dup)
2088{
2089 MAYBE_PRINTF("%d\n", res);
thughesad1c9562004-06-26 11:27:52 +00002090 if (!fd_allowed(res, "dup", tid, True)) {
jsgf855d93d2003-10-13 22:26:55 +00002091 VG_(close)(res);
2092 res = -VKI_EMFILE;
rjwalshf5f536f2003-11-17 17:45:00 +00002093 } else {
2094 if(VG_(clo_track_fds))
fitzhardinge98abfc72003-12-16 02:05:15 +00002095 record_fd_open(tid, res, VG_(resolve_filename)(res));
jsgf855d93d2003-10-13 22:26:55 +00002096 }
2097}
2098
2099PRE(dup2)
2100{
2101 /* int dup2(int oldfd, int newfd); */
2102 MAYBE_PRINTF("dup2 ( %d, %d ) ...\n", arg1,arg2);
thughesad1c9562004-06-26 11:27:52 +00002103 if (!fd_allowed(arg2, "dup2", tid, True))
jsgf855d93d2003-10-13 22:26:55 +00002104 res = -VKI_EBADF;
2105}
2106
2107POST(dup2)
2108{
2109 MAYBE_PRINTF("SYSCALL[%d] dup2 ( %d, %d ) = %d\n",
2110 VG_(getpid)(),
2111 arg1, arg2, res);
rjwalshf5f536f2003-11-17 17:45:00 +00002112 if(VG_(clo_track_fds))
fitzhardinge98abfc72003-12-16 02:05:15 +00002113 record_fd_open(tid, res, VG_(resolve_filename)(res));
jsgf855d93d2003-10-13 22:26:55 +00002114}
2115
2116PRE(fcntl)
2117{
2118 /* int fcntl(int fd, int cmd, int arg); */
2119 MAYBE_PRINTF("fcntl ( %d, %d, %d )\n",arg1,arg2,arg3);
2120}
2121
rjwalshf5f536f2003-11-17 17:45:00 +00002122POST(fcntl)
2123{
nethercote493dd182004-02-24 23:57:47 +00002124 if (arg2 == VKI_F_DUPFD) {
thughesad1c9562004-06-26 11:27:52 +00002125 if (!fd_allowed(res, "fcntl(DUPFD)", tid, True)) {
nethercote493dd182004-02-24 23:57:47 +00002126 VG_(close)(res);
2127 res = -VKI_EMFILE;
2128 } else {
2129 if (VG_(clo_track_fds))
2130 record_fd_open(tid, res, VG_(resolve_filename)(res));
2131 }
2132 }
rjwalshf5f536f2003-11-17 17:45:00 +00002133}
2134
jsgf855d93d2003-10-13 22:26:55 +00002135PRE(fchdir)
2136{
2137 /* int fchdir(int fd); */
2138 MAYBE_PRINTF("fchdir ( %d )\n", arg1);
2139}
2140
2141PRE(fchown)
2142{
2143 /* int fchown(int filedes, uid_t owner, gid_t group); */
2144 MAYBE_PRINTF("fchown ( %d, %d, %d )\n", arg1,arg2,arg3);
2145}
2146
2147PREALIAS(fchown32, fchown);
2148
2149PRE(fchmod)
2150{
2151 /* int fchmod(int fildes, mode_t mode); */
2152 MAYBE_PRINTF("fchmod ( %d, %d )\n", arg1,arg2);
2153}
2154
2155PRE(fcntl64)
2156{
rjwalshf5f536f2003-11-17 17:45:00 +00002157 /* int fcntl64(int fd, int cmd, int arg); */
2158 MAYBE_PRINTF("fcntl64 ( %d, %d, %d )\n", arg1,arg2,arg3);
2159}
2160
2161POST(fcntl64)
2162{
nethercote493dd182004-02-24 23:57:47 +00002163 if (arg2 == VKI_F_DUPFD) {
thughesad1c9562004-06-26 11:27:52 +00002164 if (!fd_allowed(res, "fcntl64(DUPFD)", tid, True)) {
nethercote493dd182004-02-24 23:57:47 +00002165 VG_(close)(res);
2166 res = -VKI_EMFILE;
2167 } else {
2168 if (VG_(clo_track_fds))
2169 record_fd_open(tid, res, VG_(resolve_filename)(res));
2170 }
2171 }
jsgf855d93d2003-10-13 22:26:55 +00002172}
2173
2174PRE(fstat)
2175{
2176 /* int fstat(int filedes, struct stat *buf); */
2177 MAYBE_PRINTF("fstat ( %d, %p )\n",arg1,arg2);
2178 SYSCALL_TRACK( pre_mem_write, tid, "fstat", arg2, sizeof(struct stat) );
2179}
2180
2181POST(fstat)
2182{
2183 VG_TRACK( post_mem_write, arg2, sizeof(struct stat) );
2184}
2185
2186static vki_ksigset_t fork_saved_mask;
2187
2188PRE(fork)
2189{
2190 vki_ksigset_t mask;
2191
2192 vg_assert(VG_(gettid)() == VG_(main_pid));
2193
2194 /* Block all signals during fork, so that we can fix things up in
2195 the child without being interrupted. */
2196 VG_(ksigfillset)(&mask);
2197 VG_(ksigprocmask)(VKI_SIG_SETMASK, &mask, &fork_saved_mask);
2198
2199 /* pid_t fork(void); */
2200 MAYBE_PRINTF("fork ()\n");
2201
2202 do_atfork_pre(tid);
2203}
2204
2205POST(fork)
2206{
2207 if (res == 0) {
2208 do_atfork_child(tid);
2209
2210 /* I am the child. Nuke all other threads which I might
2211 have inherited from my parent. POSIX mandates this. */
2212 VG_(nuke_all_threads_except)( tid );
2213
2214 /* XXX TODO: tid 1 is special, and is presumed to be present.
2215 We should move this TID to 1 in the child. */
2216
2217 /* restore signal mask */
2218 VG_(ksigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
2219 } else {
2220 MAYBE_PRINTF(" fork: process %d created child %d\n", VG_(main_pid), res);
2221
2222 do_atfork_parent(tid);
2223
2224 /* restore signal mask */
2225 VG_(ksigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
2226 }
2227}
2228
fitzhardinge47735af2004-01-21 01:27:27 +00002229PRE(clone)
2230{
2231 MAYBE_PRINTF("clone ( %d, %p, %p, %p, %p )\n",arg1,arg2,arg3,arg4,arg5);
2232
2233 if (arg2 == 0 &&
nethercotea3d718e2004-02-15 16:15:05 +00002234 (arg1 == (VKI_CLONE_CHILD_CLEARTID|VKI_CLONE_CHILD_SETTID|VKI_SIGCHLD)
2235 || arg1 == (VKI_CLONE_PARENT_SETTID|VKI_SIGCHLD)))
2236 {
fitzhardinge47735af2004-01-21 01:27:27 +00002237 before_fork(tid, tst);
2238 res = VG_(do_syscall)(SYSNO, arg1, arg2, arg3, arg4, arg5);
2239 after_fork(tid, tst);
2240 } else {
2241 VG_(unimplemented)
2242 ("clone(): not supported by Valgrind.\n "
2243 "We do now support programs linked against\n "
2244 "libpthread.so, though. Re-run with -v and ensure that\n "
2245 "you are picking up Valgrind's implementation of libpthread.so.");
2246 }
2247}
2248
jsgf855d93d2003-10-13 22:26:55 +00002249PRE(fsync)
2250{
2251 /* int fsync(int fd); */
2252 MAYBE_PRINTF("fsync ( %d )\n", arg1);
2253}
2254
2255PRE(ftruncate)
2256{
2257 /* int ftruncate(int fd, size_t length); */
2258 MAYBE_PRINTF("ftruncate ( %d, %d )\n", arg1,arg2);
2259}
2260
2261PRE(ftruncate64)
2262{
2263 /* int ftruncate64(int fd, off64_t length); */
2264 MAYBE_PRINTF("ftruncate64 ( %d, %lld )\n",
2265 arg1,arg2|((long long) arg3 << 32));
2266}
2267
2268PRE(getdents)
2269{
2270 /* int getdents(unsigned int fd, struct dirent *dirp,
2271 unsigned int count); */
2272 MAYBE_PRINTF("getdents ( %d, %p, %d )\n",arg1,arg2,arg3);
2273 SYSCALL_TRACK( pre_mem_write, tid, "getdents(dirp)", arg2, arg3 );
2274}
2275
2276POST(getdents)
2277{
2278 if (res > 0)
2279 VG_TRACK( post_mem_write, arg2, res );
2280}
2281
2282PRE(getdents64)
2283{
2284 /* int getdents(unsigned int fd, struct dirent64 *dirp,
2285 unsigned int count); */
2286 MAYBE_PRINTF("getdents64 ( %d, %p, %d )\n",arg1,arg2,arg3);
2287 SYSCALL_TRACK( pre_mem_write, tid, "getdents64(dirp)", arg2, arg3 );
2288}
2289
2290POST(getdents64)
2291{
2292 if (res > 0)
2293 VG_TRACK( post_mem_write, arg2, res );
2294}
2295
2296PRE(getgroups)
2297{
2298 /* int getgroups(int size, gid_t list[]); */
2299 MAYBE_PRINTF("getgroups ( %d, %p )\n", arg1, arg2);
2300 if (arg1 > 0)
2301 SYSCALL_TRACK( pre_mem_write, tid, "getgroups(list)", arg2,
2302 arg1 * sizeof(gid_t) );
2303}
2304
2305POST(getgroups)
2306{
2307 if (arg1 > 0 && res > 0)
2308 VG_TRACK( post_mem_write, arg2, res * sizeof(gid_t) );
2309}
2310
2311PREALIAS(getgroups32, getgroups);
2312POSTALIAS(getgroups32, getgroups);
2313
2314PRE(getcwd)
2315{
2316 /* char *getcwd(char *buf, size_t size); (but see comment below) */
2317 MAYBE_PRINTF("getcwd ( %p, %d )\n",arg1,arg2);
2318 SYSCALL_TRACK( pre_mem_write, tid, "getcwd(buf)", arg1, arg2 );
2319}
2320
2321POST(getcwd)
2322{
2323 if (res != (Addr)NULL)
2324 VG_TRACK( post_mem_write, arg1, res );
2325}
2326
2327PRE(geteuid)
2328{
2329 /* uid_t geteuid(void); */
2330 MAYBE_PRINTF("geteuid ( )\n");
2331}
2332
2333PRE(geteuid32)
2334{
2335 /* ?? uid_t geteuid32(void); */
2336 MAYBE_PRINTF("geteuid32(?) ( )\n");
2337}
2338
2339PRE(getegid)
2340{
2341 /* gid_t getegid(void); */
2342 MAYBE_PRINTF("getegid ()\n");
2343}
2344
2345PRE(getegid32)
2346{
2347 /* gid_t getegid32(void); */
2348 MAYBE_PRINTF("getegid32 ()\n");
2349}
2350
2351PRE(getgid)
2352{
2353 /* gid_t getgid(void); */
2354 MAYBE_PRINTF("getgid ()\n");
2355}
2356
2357PRE(getgid32)
2358{
2359 /* gid_t getgid32(void); */
2360 MAYBE_PRINTF("getgid32 ()\n");
2361}
2362
2363PRE(getpid)
2364{
2365 /* pid_t getpid(void); */
2366 MAYBE_PRINTF("getpid ()\n");
2367}
2368
2369PRE(getpgid)
2370{
2371 /* pid_t getpgid(pid_t pid); */
2372 MAYBE_PRINTF("getpgid ( %d )\n", arg1);
2373}
2374
2375PRE(getpgrp)
2376{
2377 /* pid_t getpgrp(void); */
2378 MAYBE_PRINTF("getpgrp ()\n");
2379}
2380
2381PRE(getppid)
2382{
2383 /* pid_t getppid(void); */
2384 MAYBE_PRINTF("getppid ()\n");
2385}
2386
2387PRE(getresgid)
2388{
2389 /* int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); */
2390 MAYBE_PRINTF("getresgid ( %p, %p, %p )\n", arg1,arg2,arg3);
2391 SYSCALL_TRACK( pre_mem_write, tid, "getresgid(rgid)",
2392 arg1, sizeof(gid_t) );
2393 SYSCALL_TRACK( pre_mem_write, tid, "getresgid(egid)",
2394 arg2, sizeof(gid_t) );
2395 SYSCALL_TRACK( pre_mem_write, tid, "getresgid(sgid)",
2396 arg3, sizeof(gid_t) );
2397}
2398
2399POST(getresgid)
2400{
2401 if (res == 0) {
2402 VG_TRACK( post_mem_write, arg1, sizeof(gid_t) );
2403 VG_TRACK( post_mem_write, arg2, sizeof(gid_t) );
2404 VG_TRACK( post_mem_write, arg3, sizeof(gid_t) );
2405 }
2406}
2407
2408PRE(getresgid32)
2409{
2410 /* int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); */
2411 MAYBE_PRINTF("getresgid32 ( %p, %p, %p )\n", arg1,arg2,arg3);
2412 SYSCALL_TRACK( pre_mem_write, tid, "getresgid32(rgid)",
2413 arg1, sizeof(gid_t) );
2414 SYSCALL_TRACK( pre_mem_write, tid, "getresgid32(egid)",
2415 arg2, sizeof(gid_t) );
2416 SYSCALL_TRACK( pre_mem_write, tid, "getresgid32(sgid)",
2417 arg3, sizeof(gid_t) );
2418}
2419
2420POST(getresgid32)
2421{
2422 if (res == 0) {
2423 VG_TRACK( post_mem_write, arg1, sizeof(gid_t) );
2424 VG_TRACK( post_mem_write, arg2, sizeof(gid_t) );
2425 VG_TRACK( post_mem_write, arg3, sizeof(gid_t) );
2426 }
2427}
2428
2429PRE(getresuid)
2430{
2431 /* int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); */
2432 MAYBE_PRINTF("getresuid ( %p, %p, %p )\n", arg1,arg2,arg3);
2433 SYSCALL_TRACK( pre_mem_write, tid, "getresuid(ruid)",
2434 arg1, sizeof(uid_t) );
2435 SYSCALL_TRACK( pre_mem_write, tid, "getresuid(euid)",
2436 arg2, sizeof(uid_t) );
2437 SYSCALL_TRACK( pre_mem_write, tid, "getresuid(suid)",
2438 arg3, sizeof(uid_t) );
2439}
2440
2441POST(getresuid)
2442{
2443 if (res == 0) {
2444 VG_TRACK( post_mem_write, arg1, sizeof(uid_t) );
2445 VG_TRACK( post_mem_write, arg2, sizeof(uid_t) );
2446 VG_TRACK( post_mem_write, arg3, sizeof(uid_t) );
2447 }
2448}
2449
2450PRE(getresuid32)
2451{
2452 /* int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); */
2453 MAYBE_PRINTF("getresuid32 ( %p, %p, %p )\n", arg1,arg2,arg3);
2454 SYSCALL_TRACK( pre_mem_write, tid, "getresuid32(ruid)",
2455 arg1, sizeof(uid_t) );
2456 SYSCALL_TRACK( pre_mem_write, tid, "getresuid32(euid)",
2457 arg2, sizeof(uid_t) );
2458 SYSCALL_TRACK( pre_mem_write, tid, "getresuid32(suid)",
2459 arg3, sizeof(uid_t) );
2460}
2461
2462POST(getresuid32)
2463{
2464 if (res == 0) {
2465 VG_TRACK( post_mem_write, arg1, sizeof(uid_t) );
2466 VG_TRACK( post_mem_write, arg2, sizeof(uid_t) );
2467 VG_TRACK( post_mem_write, arg3, sizeof(uid_t) );
2468 }
2469}
2470
2471PRE(getrlimit)
2472{
2473 /* int getrlimit (int resource, struct rlimit *rlim); */
2474 MAYBE_PRINTF("getrlimit ( %d, %p )\n", arg1,arg2);
2475 SYSCALL_TRACK( pre_mem_write, tid, "getrlimit(rlim)", arg2,
fitzhardingeb50068f2004-02-24 23:42:55 +00002476 sizeof(struct vki_rlimit) );
jsgf855d93d2003-10-13 22:26:55 +00002477}
2478
2479POST(getrlimit)
2480{
fitzhardingeb50068f2004-02-24 23:42:55 +00002481 VG_TRACK( post_mem_write, arg2, sizeof(struct vki_rlimit) );
nethercote535f03b2004-02-15 15:32:51 +00002482
fitzhardingeb50068f2004-02-24 23:42:55 +00002483 switch(arg1) {
2484 case VKI_RLIMIT_NOFILE:
thughesad1c9562004-06-26 11:27:52 +00002485 ((vki_rlimit *)arg2)->rlim_cur = VG_(fd_soft_limit);
2486 ((vki_rlimit *)arg2)->rlim_max = VG_(fd_hard_limit);
fitzhardingeb50068f2004-02-24 23:42:55 +00002487 break;
2488
2489 case VKI_RLIMIT_DATA:
2490 *((vki_rlimit *)arg2) = VG_(client_rlimit_data);
2491 break;
2492 }
jsgf855d93d2003-10-13 22:26:55 +00002493}
2494
2495PREALIAS(ugetrlimit, getrlimit);
2496POSTALIAS(ugetrlimit, getrlimit);
2497
2498PRE(getrusage)
2499{
2500 /* int getrusage (int who, struct rusage *usage); */
2501 MAYBE_PRINTF("getrusage ( %d, %p )\n", arg1,arg2);
2502 SYSCALL_TRACK( pre_mem_write, tid, "getrusage(usage)", arg2,
2503 sizeof(struct rusage) );
2504}
2505
2506POST(getrusage)
2507{
2508 if (res == 0)
2509 VG_TRACK( post_mem_write,arg2, sizeof(struct rusage) );
2510}
2511
2512PRE(gettimeofday)
2513{
2514 /* int gettimeofday(struct timeval *tv, struct timezone *tz); */
2515 MAYBE_PRINTF("gettimeofday ( %p, %p )\n",arg1,arg2);
2516 SYSCALL_TRACK( pre_mem_write, tid, "gettimeofday(tv)", arg1,
2517 sizeof(struct timeval) );
2518 if (arg2 != 0)
2519 SYSCALL_TRACK( pre_mem_write, tid, "gettimeofday(tz)", arg2,
2520 sizeof(struct timezone) );
2521}
2522
2523POST(gettimeofday)
2524{
2525 if (res == 0) {
2526 VG_TRACK( post_mem_write, arg1, sizeof(struct timeval) );
2527 if (arg2 != 0)
2528 VG_TRACK( post_mem_write, arg2, sizeof(struct timezone) );
2529 }
2530}
2531
2532PRE(getuid)
2533{
2534 /* uid_t getuid(void); */
2535 MAYBE_PRINTF("getuid ( )\n");
2536}
2537
2538PRE(getuid32)
2539{
2540 /* ???uid_t getuid32(void); */
2541 MAYBE_PRINTF("getuid32 ( )\n");
2542}
2543
2544PRE(ipc)
2545{
2546 MAYBE_PRINTF("ipc ( %d, %d, %d, %d, %p, %d )\n",
2547 arg1,arg2,arg3,arg4,arg5,arg6);
2548 switch (arg1 /* call */) {
2549 case 1: /* IPCOP_semop */
2550 SYSCALL_TRACK( pre_mem_read, tid, "semop(sops)", arg5,
2551 arg3 * sizeof(struct sembuf) );
2552 break;
2553 case 2: /* IPCOP_semget */
2554 case 3: /* IPCOP_semctl */
2555 break;
thughes03766282004-06-13 14:23:00 +00002556 case 4: /* IPCOP_semtimedop */
2557 SYSCALL_TRACK( pre_mem_read, tid, "semtimedop(sops)", arg5,
2558 arg3 * sizeof(struct sembuf) );
2559 if (arg6 != (UInt)NULL)
2560 SYSCALL_TRACK( pre_mem_read, tid, "semtimedop(timeout)", arg5,
2561 sizeof(struct timespec) );
2562 break;
jsgf855d93d2003-10-13 22:26:55 +00002563 case 11: /* IPCOP_msgsnd */
2564 {
2565 struct msgbuf *msgp = (struct msgbuf *)arg5;
2566 Int msgsz = arg3;
2567
2568 SYSCALL_TRACK( pre_mem_read, tid, "msgsnd(msgp->mtype)",
2569 (UInt)&msgp->mtype, sizeof(msgp->mtype) );
2570 SYSCALL_TRACK( pre_mem_read, tid, "msgsnd(msgp->mtext)",
2571 (UInt)msgp->mtext, msgsz );
2572 break;
2573 }
2574 case 12: /* IPCOP_msgrcv */
2575 {
2576 struct msgbuf *msgp;
2577 Int msgsz = arg3;
2578
2579 msgp = (struct msgbuf *)deref_Addr( tid,
2580 (Addr) (&((struct ipc_kludge *)arg5)->msgp),
2581 "msgrcv(msgp)" );
2582
2583 SYSCALL_TRACK( pre_mem_write, tid, "msgrcv(msgp->mtype)",
2584 (UInt)&msgp->mtype, sizeof(msgp->mtype) );
2585 SYSCALL_TRACK( pre_mem_write, tid, "msgrcv(msgp->mtext)",
2586 (UInt)msgp->mtext, msgsz );
2587 break;
2588 }
2589 case 13: /* IPCOP_msgget */
2590 break;
2591 case 14: /* IPCOP_msgctl */
2592 {
2593 switch (arg3 /* cmd */) {
2594 case IPC_STAT:
2595 SYSCALL_TRACK( pre_mem_write, tid, "msgctl(buf)", arg5,
2596 sizeof(struct msqid_ds) );
2597 break;
2598 case IPC_SET:
2599 SYSCALL_TRACK( pre_mem_read, tid, "msgctl(buf)", arg5,
2600 sizeof(struct msqid_ds) );
2601 break;
2602# if defined(IPC_64)
2603 case IPC_STAT|IPC_64:
2604 SYSCALL_TRACK( pre_mem_write, tid, "msgctl(buf)", arg5,
2605 sizeof(struct msqid64_ds) );
2606 break;
2607# endif
2608# if defined(IPC_64)
2609 case IPC_SET|IPC_64:
2610 SYSCALL_TRACK( pre_mem_read, tid, "msgctl(buf)", arg5,
2611 sizeof(struct msqid64_ds) );
2612 break;
2613# endif
2614 default:
2615 break;
2616 }
2617 break;
2618 }
2619 case 21: /* IPCOP_shmat */
2620 {
fitzhardinge98abfc72003-12-16 02:05:15 +00002621 UInt shmid = arg2;
2622 UInt segmentSize = get_shm_size ( shmid );
2623
2624 /* If they didn't ask for a particular address, then place it
2625 like an mmap. */
2626 if (arg5 == 0)
2627 arg5 = VG_(find_map_space)(0, segmentSize, True);
2628 else if (!valid_client_addr(arg5, segmentSize, tid, "shmat"))
2629 res = -VKI_EINVAL;
jsgf855d93d2003-10-13 22:26:55 +00002630 break;
2631 }
2632 case 22: /* IPCOP_shmdt */
fitzhardinged25e8a22004-02-25 00:07:10 +00002633 if (!valid_client_addr(arg5, 1, tid, "shmdt"))
fitzhardinge1a303042003-12-22 08:48:50 +00002634 res = -VKI_EINVAL;
jsgf855d93d2003-10-13 22:26:55 +00002635 break;
2636 case 23: /* IPCOP_shmget */
2637 break;
2638 case 24: /* IPCOP_shmctl */
2639 /* Subject: shmctl: The True Story
2640 Date: Thu, 9 May 2002 18:07:23 +0100 (BST)
2641 From: Reuben Thomas <rrt@mupsych.org>
2642 To: Julian Seward <jseward@acm.org>
2643
2644 1. As you suggested, the syscall subop is in arg1.
2645
2646 2. There are a couple more twists, so the arg order
2647 is actually:
2648
2649 arg1 syscall subop
2650 arg2 file desc
2651 arg3 shm operation code (can have IPC_64 set)
2652 arg4 0 ??? is arg3-arg4 a 64-bit quantity when IPC_64
2653 is defined?
2654 arg5 pointer to buffer
2655
2656 3. With this in mind, I've amended the case as below:
2657 */
2658 {
2659 UInt cmd = arg3;
2660 Bool out_arg = False;
2661 if ( arg5 ) {
2662# if defined(IPC_64)
2663 cmd = cmd & (~IPC_64);
2664# endif
2665 out_arg = cmd == SHM_STAT || cmd == IPC_STAT;
2666 if ( out_arg )
2667 SYSCALL_TRACK( pre_mem_write, tid,
2668 "shmctl(SHM_STAT or IPC_STAT,buf)",
2669 arg5, sizeof(struct shmid_ds) );
2670 else
2671 SYSCALL_TRACK( pre_mem_read, tid,
2672 "shmctl(SHM_XXXX,buf)",
2673 arg5, sizeof(struct shmid_ds) );
2674 }
2675 }
2676 break;
2677 default:
2678 VG_(message)(Vg_DebugMsg,
2679 "FATAL: unhandled syscall(ipc) %d",
2680 arg1 );
2681 VG_(core_panic)("... bye!\n");
2682 break; /*NOTREACHED*/
2683 }
2684}
2685
2686POST(ipc)
2687{
2688 switch (arg1 /* call */) {
2689 case 1: /* IPCOP_semop */
jsgf855d93d2003-10-13 22:26:55 +00002690 case 2: /* IPCOP_semget */
2691 case 3: /* IPCOP_semctl */
thughes03766282004-06-13 14:23:00 +00002692 case 4: /* IPCOP_semtimedop */
jsgf855d93d2003-10-13 22:26:55 +00002693 break;
2694 case 11: /* IPCOP_msgsnd */
2695 break;
2696 case 12: /* IPCOP_msgrcv */
2697 {
2698 struct msgbuf *msgp;
2699
2700 msgp = (struct msgbuf *)deref_Addr( tid,
2701 (Addr) (&((struct ipc_kludge *)arg5)->msgp),
2702 "msgrcv(msgp)" );
2703 if ( res > 0 ) {
2704 VG_TRACK( post_mem_write, (UInt)&msgp->mtype,
2705 sizeof(msgp->mtype) );
2706 VG_TRACK( post_mem_write, (UInt)msgp->mtext, res );
2707 }
2708 break;
2709 }
2710 case 13: /* IPCOP_msgget */
2711 break;
2712 case 14: /* IPCOP_msgctl */
2713 {
2714 switch (arg3 /* cmd */) {
2715 case IPC_STAT:
2716 if ( res > 0 ) {
2717 VG_TRACK( post_mem_write, arg5,
2718 sizeof(struct msqid_ds) );
2719 }
2720 break;
2721 case IPC_SET:
2722 break;
2723# if defined(IPC_64)
2724 case IPC_STAT|IPC_64:
2725 if ( res > 0 ) {
2726 VG_TRACK( post_mem_write, arg5,
2727 sizeof(struct msqid64_ds) );
2728 }
2729 break;
2730# endif
2731# if defined(IPC_64)
2732 case IPC_SET|IPC_64:
2733 break;
2734# endif
2735 default:
2736 break;
2737 }
2738 break;
2739 }
2740 case 21: /* IPCOP_shmat */
2741 {
2742 Int shmid = arg2;
fitzhardinge98abfc72003-12-16 02:05:15 +00002743 Int shmflag = arg3;
jsgf855d93d2003-10-13 22:26:55 +00002744 Addr addr;
2745
jsgf855d93d2003-10-13 22:26:55 +00002746 /* force readability. before the syscall it is
2747 * indeed uninitialized, as can be seen in
2748 * glibc/sysdeps/unix/sysv/linux/shmat.c */
2749 VG_TRACK( post_mem_write, arg4, sizeof( ULong ) );
2750
2751 addr = deref_Addr ( tid, arg4, "shmat(addr)" );
2752 if ( addr > 0 ) {
2753 UInt segmentSize = get_shm_size ( shmid );
2754 if ( segmentSize > 0 ) {
nethercote27ea8bc2004-07-10 17:21:14 +00002755 UInt prot = VKI_PROT_READ|VKI_PROT_WRITE;
jsgf855d93d2003-10-13 22:26:55 +00002756 /* we don't distinguish whether it's read-only or
2757 * read-write -- it doesn't matter really. */
nethercote071c84a2004-07-10 17:30:07 +00002758 VG_TRACK( new_mem_mmap, addr, segmentSize, True, True, False );
fitzhardinge98abfc72003-12-16 02:05:15 +00002759
fitzhardinge98abfc72003-12-16 02:05:15 +00002760 if (!(shmflag & 010000)) /* = SHM_RDONLY */
2761 prot &= ~VKI_PROT_WRITE;
nethercote27ea8bc2004-07-10 17:21:14 +00002762 VG_(map_segment)(addr, segmentSize, prot, SF_SHARED|SF_SHM);
jsgf855d93d2003-10-13 22:26:55 +00002763 }
2764 }
2765 break;
2766 }
2767 case 22: /* IPCOP_shmdt */
fitzhardinge98abfc72003-12-16 02:05:15 +00002768 {
fitzhardinged25e8a22004-02-25 00:07:10 +00002769 Segment *s = VG_(find_segment)(arg5);
fitzhardinge98abfc72003-12-16 02:05:15 +00002770
fitzhardinged25e8a22004-02-25 00:07:10 +00002771 if (s != NULL && (s->flags & SF_SHM) && VG_(seg_contains)(s, arg5, 1)) {
fitzhardinge98abfc72003-12-16 02:05:15 +00002772 VG_TRACK( die_mem_munmap, s->addr, s->len );
2773 VG_(unmap_range)(s->addr, s->len);
2774 }
jsgf855d93d2003-10-13 22:26:55 +00002775 break;
fitzhardinge98abfc72003-12-16 02:05:15 +00002776 }
jsgf855d93d2003-10-13 22:26:55 +00002777 case 23: /* IPCOP_shmget */
2778 break;
2779 case 24: /* IPCOP_shmctl */
2780 /* Subject: shmctl: The True Story
2781 Date: Thu, 9 May 2002 18:07:23 +0100 (BST)
2782 From: Reuben Thomas <rrt@mupsych.org>
2783 To: Julian Seward <jseward@acm.org>
2784
2785 1. As you suggested, the syscall subop is in arg1.
2786
2787 2. There are a couple more twists, so the arg order
2788 is actually:
2789
2790 arg1 syscall subop
2791 arg2 file desc
2792 arg3 shm operation code (can have IPC_64 set)
2793 arg4 0 ??? is arg3-arg4 a 64-bit quantity when IPC_64
2794 is defined?
2795 arg5 pointer to buffer
2796
2797 3. With this in mind, I've amended the case as below:
2798 */
2799 {
2800 UInt cmd = arg3;
2801 Bool out_arg = False;
2802 if ( arg5 ) {
2803# if defined(IPC_64)
2804 cmd = cmd & (~IPC_64);
2805# endif
2806 out_arg = cmd == SHM_STAT || cmd == IPC_STAT;
2807 }
2808 if ( arg5 && res == 0 && out_arg )
2809 VG_TRACK( post_mem_write, arg5,
2810 sizeof(struct shmid_ds) );
2811 }
2812 break;
2813 default:
2814 VG_(message)(Vg_DebugMsg,
2815 "FATAL: unhandled syscall(ipc) %d",
2816 arg1 );
2817 VG_(core_panic)("... bye!\n");
2818 break; /*NOTREACHED*/
2819 }
2820}
2821
2822PRE(ioctl)
2823{
2824 /* int ioctl(int d, int request, ...)
2825 [The "third" argument is traditionally char *argp,
2826 and will be so named for this discussion.]
2827 */
2828 /*
2829 VG_(message)(
2830 Vg_DebugMsg,
2831 "is an IOCTL, request = 0x%x, d = %d, argp = 0x%x",
2832 arg2,arg1,arg3);
2833 */
2834 MAYBE_PRINTF("ioctl ( %d, 0x%x, %p )\n",arg1,arg2,arg3);
2835 switch (arg2 /* request */) {
2836 case TCSETS:
2837 case TCSETSW:
2838 case TCSETSF:
2839 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TCSET{S,SW,SF})", arg3,
2840 VKI_SIZEOF_STRUCT_TERMIOS );
2841 break;
2842 case TCGETS:
2843 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TCGETS)", arg3,
2844 VKI_SIZEOF_STRUCT_TERMIOS );
2845 break;
2846 case TCSETA:
2847 case TCSETAW:
2848 case TCSETAF:
2849 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TCSET{A,AW,AF})", arg3,
2850 VKI_SIZEOF_STRUCT_TERMIO );
2851 break;
2852 case TCGETA:
2853 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TCGETA)", arg3,
2854 VKI_SIZEOF_STRUCT_TERMIO );
2855 break;
2856 case TCSBRK:
2857 case TCXONC:
2858 case TCSBRKP:
2859 case TCFLSH:
2860 /* These just take an int by value */
2861 break;
2862 case TIOCGWINSZ:
2863 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TIOCGWINSZ)", arg3,
2864 sizeof(struct winsize) );
2865 break;
2866 case TIOCSWINSZ:
2867 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TIOCSWINSZ)", arg3,
2868 sizeof(struct winsize) );
2869 break;
2870 case TIOCLINUX:
2871 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TIOCLINUX)", arg3,
2872 sizeof(char *) );
2873 if (*(char *)arg3 == 11) {
2874 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TIOCLINUX, 11)",
2875 arg3, 2 * sizeof(char *) );
2876 }
2877 break;
2878 case TIOCGPGRP:
2879 /* Get process group ID for foreground processing group. */
2880 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TIOCGPGRP)", arg3,
2881 sizeof(pid_t) );
2882 break;
2883 case TIOCSPGRP:
2884 /* Set a process group ID? */
2885 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TIOCGPGRP)", arg3,
2886 sizeof(pid_t) );
2887 break;
2888 case TIOCGPTN: /* Get Pty Number (of pty-mux device) */
2889 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TIOCGPTN)",
2890 arg3, sizeof(int) );
2891 break;
2892 case TIOCSCTTY:
2893 /* Just takes an int value. */
2894 break;
2895 case TIOCSPTLCK: /* Lock/unlock Pty */
2896 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TIOCSPTLCK)",
2897 arg3, sizeof(int) );
2898 break;
2899 case FIONBIO:
2900 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(FIONBIO)",
2901 arg3, sizeof(int) );
2902 break;
2903 case FIOASYNC:
2904 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(FIOASYNC)",
2905 arg3, sizeof(int) );
2906 break;
2907 case FIONREAD: /* identical to SIOCINQ */
2908 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(FIONREAD)",
2909 arg3, sizeof(int) );
2910 break;
2911
2912 /* If you get compilation problems here, change the #if
2913 1 to #if 0 and get rid of <scsi/sg.h> in
2914 vg_unsafe.h. */
2915# if 1
2916 case SG_SET_COMMAND_Q:
2917 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SG_SET_COMMAND_Q)",
2918 arg3, sizeof(int) );
2919 break;
2920# if defined(SG_IO)
2921 case SG_IO:
2922 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SG_IO)", arg3,
2923 sizeof(struct sg_io_hdr) );
2924 break;
2925# endif /* SG_IO */
2926 case SG_GET_SCSI_ID:
2927 /* Note: sometimes sg_scsi_id is called sg_scsi_id_t */
2928 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SG_GET_SCSI_ID)", arg3,
2929 sizeof(struct sg_scsi_id) );
2930 break;
2931 case SG_SET_RESERVED_SIZE:
2932 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SG_SET_RESERVED_SIZE)",
2933 arg3, sizeof(int) );
2934 break;
2935 case SG_SET_TIMEOUT:
2936 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SG_SET_TIMEOUT)", arg3,
2937 sizeof(int) );
2938 break;
2939 case SG_GET_RESERVED_SIZE:
2940 SYSCALL_TRACK( pre_mem_write, tid,
2941 "ioctl(SG_GET_RESERVED_SIZE)", arg3,
2942 sizeof(int) );
2943 break;
2944 case SG_GET_TIMEOUT:
2945 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SG_GET_TIMEOUT)", arg3,
2946 sizeof(int) );
2947 break;
2948 case SG_GET_VERSION_NUM:
2949 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SG_GET_VERSION_NUM)",
2950 arg3, sizeof(int) );
2951 break;
2952# endif
2953
muellera4b153a2003-11-19 22:07:14 +00002954 case VKI_IIOCGETCPS:
jsgf855d93d2003-10-13 22:26:55 +00002955 /* In early 2.4 kernels, ISDN_MAX_CHANNELS was only defined
2956 * when KERNEL was. I never saw a larger value than 64 though */
2957# ifndef ISDN_MAX_CHANNELS
2958# define ISDN_MAX_CHANNELS 64
2959# endif
2960 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(IIOCGETCPS)", arg3,
2961 ISDN_MAX_CHANNELS
2962 * 2 * sizeof(unsigned long) );
2963 break;
muellera4b153a2003-11-19 22:07:14 +00002964 case VKI_IIOCNETGPN:
jsgf855d93d2003-10-13 22:26:55 +00002965 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(IIOCNETGPN)",
2966 (UInt)&((isdn_net_ioctl_phone *)arg3)->name,
2967 sizeof(((isdn_net_ioctl_phone *)arg3)->name) );
2968 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(IIOCNETGPN)", arg3,
2969 sizeof(isdn_net_ioctl_phone) );
2970 break;
2971
2972 /* These all use struct ifreq AFAIK */
thughesbe811712004-06-17 23:04:58 +00002973 case SIOCGIFINDEX: /* get iface index */
2974 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCGIFINDEX)",
2975 (UInt)((struct ifreq *)arg3)->ifr_name );
2976 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFINDEX)", arg3,
jsgf855d93d2003-10-13 22:26:55 +00002977 sizeof(struct ifreq));
2978 break;
thughesbe811712004-06-17 23:04:58 +00002979 case SIOCGIFFLAGS: /* get flags */
2980 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCGIFFLAGS)",
2981 (UInt)((struct ifreq *)arg3)->ifr_name );
2982 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFFLAGS)", arg3,
2983 sizeof(struct ifreq));
2984 break;
2985 case SIOCGIFHWADDR: /* Get hardware address */
2986 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCGIFHWADDR)",
2987 (UInt)((struct ifreq *)arg3)->ifr_name );
2988 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFHWADDR)", arg3,
2989 sizeof(struct ifreq));
2990 break;
2991 case SIOCGIFMTU: /* get MTU size */
2992 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCGIFMTU)",
2993 (UInt)((struct ifreq *)arg3)->ifr_name );
2994 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFMTU)", arg3,
2995 sizeof(struct ifreq));
2996 break;
2997 case SIOCGIFADDR: /* get PA address */
2998 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCGIFADDR)",
2999 (UInt)((struct ifreq *)arg3)->ifr_name );
3000 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFADDR)", arg3,
3001 sizeof(struct ifreq));
3002 break;
3003 case SIOCGIFNETMASK: /* get network PA mask */
3004 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCGIFNETMASK)",
3005 (UInt)((struct ifreq *)arg3)->ifr_name );
3006 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFNETMASK)", arg3,
3007 sizeof(struct ifreq));
3008 break;
3009 case SIOCGIFMETRIC: /* get metric */
3010 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCGIFMETRIC)",
3011 (UInt)((struct ifreq *)arg3)->ifr_name );
3012 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFMETRIC)", arg3,
3013 sizeof(struct ifreq));
3014 break;
3015 case SIOCGIFMAP: /* Get device parameters */
3016 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCGIFMAP)",
3017 (UInt)((struct ifreq *)arg3)->ifr_name );
3018 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFMAP)", arg3,
3019 sizeof(struct ifreq));
3020 break;
3021 case SIOCGIFTXQLEN: /* Get the tx queue length */
3022 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCGIFTXQLEN)",
3023 (UInt)((struct ifreq *)arg3)->ifr_name );
3024 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFTXQLEN)", arg3,
3025 sizeof(struct ifreq));
3026 break;
3027 case SIOCGIFDSTADDR: /* get remote PA address */
3028 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCGIFDSTADDR)",
3029 (UInt)((struct ifreq *)arg3)->ifr_name );
3030 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFDSTADDR)", arg3,
3031 sizeof(struct ifreq));
3032 break;
3033 case SIOCGIFBRDADDR: /* get broadcast PA address */
3034 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCGIFBRDADDR)",
3035 (UInt)((struct ifreq *)arg3)->ifr_name );
3036 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFBRDADDR)", arg3,
3037 sizeof(struct ifreq));
3038 break;
3039 case SIOCGIFNAME: /* get iface name */
3040 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCGIFNAME)",
3041 (UInt)((struct ifreq *)arg3)->ifr_ifindex,
3042 sizeof(((struct ifreq *)arg3)->ifr_ifindex) );
3043 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFNAME)", arg3,
3044 sizeof(struct ifreq));
3045 break;
3046#ifdef HAVE_LINUX_MII_H
3047 case SIOCGMIIPHY: /* get hardware entry */
3048 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCGIFMIIPHY)",
3049 (UInt)((struct ifreq *)arg3)->ifr_name );
3050 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFMIIPHY)", arg3,
3051 sizeof(struct ifreq));
3052 break;
3053 case SIOCGMIIREG: /* get hardware entry registers */
3054 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCGIFMIIREG)",
3055 (UInt)((struct ifreq *)arg3)->ifr_name );
3056 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCGIFMIIREG)",
3057 (UInt)&((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->phy_id,
3058 sizeof(((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->phy_id) );
3059 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCGIFMIIREG)",
3060 (UInt)&((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->reg_num,
3061 sizeof(((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->reg_num) );
3062 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SIOCGIFMIIREG)", arg3,
3063 sizeof(struct ifreq));
3064 break;
3065#endif
jsgf855d93d2003-10-13 22:26:55 +00003066 case SIOCGIFCONF: /* get iface list */
3067 /* WAS:
3068 SYSCALL_TRACK( pre_mem_write,"ioctl(SIOCGIFCONF)", arg3,
3069 sizeof(struct ifconf));
3070 KERNEL_DO_SYSCALL(tid,res);
3071 if (!VG_(is_kerror)(res) && res == 0)
3072 VG_TRACK( post_mem_write,arg3, sizeof(struct ifconf));
3073 */
3074 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(SIOCGIFCONF)", arg3,
3075 sizeof(struct ifconf));
3076 if ( arg3 ) {
3077 // TODO len must be readable and writable
3078 // buf pointer only needs to be readable
3079 struct ifconf *ifc = (struct ifconf *) arg3;
3080 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SIOCGIFCONF).ifc_buf",
3081 (Addr)(ifc->ifc_buf), (UInt)(ifc->ifc_len) );
3082 }
3083 break;
3084 case SIOCGSTAMP:
3085 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SIOCGSTAMP)", arg3,
3086 sizeof(struct timeval));
3087 break;
3088 /* SIOCOUTQ is an ioctl that, when called on a socket, returns
3089 the number of bytes currently in that socket's send buffer.
3090 It writes this value as an int to the memory location
3091 indicated by the third argument of ioctl(2). */
3092 case SIOCOUTQ:
3093 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SIOCOUTQ)", arg3,
3094 sizeof(int));
3095 break;
3096 case SIOCGRARP: /* get RARP table entry */
3097 case SIOCGARP: /* get ARP table entry */
3098 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SIOCGARP)", arg3,
3099 sizeof(struct arpreq));
3100 break;
3101
3102 case SIOCSIFFLAGS: /* set flags */
thughesbe811712004-06-17 23:04:58 +00003103 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCSIFFLAGS)",
3104 (UInt)((struct ifreq *)arg3)->ifr_name );
3105 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCSIFFLAGS)",
3106 (UInt)&((struct ifreq *)arg3)->ifr_flags,
3107 sizeof(((struct ifreq *)arg3)->ifr_flags) );
3108 break;
jsgf855d93d2003-10-13 22:26:55 +00003109 case SIOCSIFMAP: /* Set device parameters */
thughesbe811712004-06-17 23:04:58 +00003110 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCSIFMAP)",
3111 (UInt)((struct ifreq *)arg3)->ifr_name );
3112 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCSIFMAP)",
3113 (UInt)&((struct ifreq *)arg3)->ifr_map,
3114 sizeof(((struct ifreq *)arg3)->ifr_map) );
3115 break;
jsgf855d93d2003-10-13 22:26:55 +00003116 case SIOCSIFTXQLEN: /* Set the tx queue length */
thughesbe811712004-06-17 23:04:58 +00003117 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCSIFTXQLEN)",
3118 (UInt)((struct ifreq *)arg3)->ifr_name );
3119 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCSIFTXQLEN)",
3120 (UInt)&((struct ifreq *)arg3)->ifr_qlen,
3121 sizeof(((struct ifreq *)arg3)->ifr_qlen) );
3122 break;
3123 case SIOCSIFADDR: /* set PA address */
jsgf855d93d2003-10-13 22:26:55 +00003124 case SIOCSIFDSTADDR: /* set remote PA address */
3125 case SIOCSIFBRDADDR: /* set broadcast PA address */
3126 case SIOCSIFNETMASK: /* set network PA mask */
thughesbe811712004-06-17 23:04:58 +00003127 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCSIF*ADDR)",
3128 (UInt)((struct ifreq *)arg3)->ifr_name );
3129 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCSIF*ADDR)",
3130 (UInt)&((struct ifreq *)arg3)->ifr_addr,
3131 sizeof(((struct ifreq *)arg3)->ifr_addr) );
jsgf855d93d2003-10-13 22:26:55 +00003132 break;
thughesbe811712004-06-17 23:04:58 +00003133 case SIOCSIFMETRIC: /* set metric */
3134 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCSIFMETRIC)",
3135 (UInt)((struct ifreq *)arg3)->ifr_name );
3136 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCSIFMETRIC)",
3137 (UInt)&((struct ifreq *)arg3)->ifr_metric,
3138 sizeof(((struct ifreq *)arg3)->ifr_metric) );
3139 break;
3140 case SIOCSIFMTU: /* set MTU size */
3141 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCSIFMTU)",
3142 (UInt)((struct ifreq *)arg3)->ifr_name );
3143 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCSIFMTU)",
3144 (UInt)&((struct ifreq *)arg3)->ifr_mtu,
3145 sizeof(((struct ifreq *)arg3)->ifr_mtu) );
3146 break;
3147 case SIOCSIFHWADDR: /* set hardware address */
3148 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCSIFHWADDR)",
3149 (UInt)((struct ifreq *)arg3)->ifr_name );
3150 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCSIFHWADDR)",
3151 (UInt)&((struct ifreq *)arg3)->ifr_hwaddr,
3152 sizeof(((struct ifreq *)arg3)->ifr_hwaddr) );
3153 break;
3154#ifdef HAVE_LINUX_MII_H
3155 case SIOCSMIIREG: /* set hardware entry registers */
3156 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "ioctl(SIOCSMIIREG)",
3157 (UInt)((struct ifreq *)arg3)->ifr_name );
3158 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCSMIIREG)",
3159 (UInt)&((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->phy_id,
3160 sizeof(((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->phy_id) );
3161 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCSMIIREG)",
3162 (UInt)&((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->reg_num,
3163 sizeof(((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->reg_num) );
3164 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCSMIIREG)",
3165 (UInt)&((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->val_in,
3166 sizeof(((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->val_in) );
3167 break;
3168#endif
jsgf855d93d2003-10-13 22:26:55 +00003169 /* Routing table calls. */
3170 case SIOCADDRT: /* add routing table entry */
3171 case SIOCDELRT: /* delete routing table entry */
3172 SYSCALL_TRACK( pre_mem_read,tid,"ioctl(SIOCADDRT/DELRT)", arg3,
3173 sizeof(struct rtentry));
3174 break;
3175
3176 /* RARP cache control calls. */
3177 case SIOCDRARP: /* delete RARP table entry */
3178 case SIOCSRARP: /* set RARP table entry */
3179 /* ARP cache control calls. */
3180 case SIOCSARP: /* set ARP table entry */
3181 case SIOCDARP: /* delete ARP table entry */
3182 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(SIOCSIFFLAGS)", arg3,
3183 sizeof(struct ifreq));
3184 break;
3185
3186 case SIOCSPGRP:
3187 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCSPGRP)", arg3,
3188 sizeof(int) );
3189 break;
3190
3191 /* linux/soundcard interface (OSS) */
3192 case SNDCTL_SEQ_GETOUTCOUNT:
3193 case SNDCTL_SEQ_GETINCOUNT:
3194 case SNDCTL_SEQ_PERCMODE:
3195 case SNDCTL_SEQ_TESTMIDI:
3196 case SNDCTL_SEQ_RESETSAMPLES:
3197 case SNDCTL_SEQ_NRSYNTHS:
3198 case SNDCTL_SEQ_NRMIDIS:
3199 case SNDCTL_SEQ_GETTIME:
3200 case SNDCTL_DSP_GETFMTS:
3201 case SNDCTL_DSP_GETTRIGGER:
3202 case SNDCTL_DSP_GETODELAY:
3203# if defined(SNDCTL_DSP_GETSPDIF)
3204 case SNDCTL_DSP_GETSPDIF:
3205# endif
3206 case SNDCTL_DSP_GETCAPS:
3207 case SOUND_PCM_READ_RATE:
3208 case SOUND_PCM_READ_CHANNELS:
3209 case SOUND_PCM_READ_BITS:
3210 case (SOUND_PCM_READ_BITS|0x40000000): /* what the fuck ? */
3211 case SOUND_PCM_READ_FILTER:
3212 SYSCALL_TRACK( pre_mem_write,tid,
3213 "ioctl(SNDCTL_XXX|SOUND_XXX (SIOR, int))",
3214 arg3,
3215 sizeof(int));
3216 break;
3217 case SNDCTL_SEQ_CTRLRATE:
3218 case SNDCTL_DSP_SPEED:
3219 case SNDCTL_DSP_STEREO:
3220 case SNDCTL_DSP_GETBLKSIZE:
3221 case SNDCTL_DSP_CHANNELS:
3222 case SOUND_PCM_WRITE_FILTER:
3223 case SNDCTL_DSP_SUBDIVIDE:
3224 case SNDCTL_DSP_SETFRAGMENT:
3225# if defined(SNDCTL_DSP_GETCHANNELMASK)
3226 case SNDCTL_DSP_GETCHANNELMASK:
3227# endif
3228# if defined(SNDCTL_DSP_BIND_CHANNEL)
3229 case SNDCTL_DSP_BIND_CHANNEL:
3230# endif
3231 case SNDCTL_TMR_TIMEBASE:
3232 case SNDCTL_TMR_TEMPO:
3233 case SNDCTL_TMR_SOURCE:
3234 case SNDCTL_MIDI_PRETIME:
3235 case SNDCTL_MIDI_MPUMODE:
3236 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(SNDCTL_XXX|SOUND_XXX "
3237 "(SIOWR, int))",
3238 arg3, sizeof(int));
3239 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SNDCTL_XXX|SOUND_XXX "
3240 "(SIOWR, int))",
3241 arg3, sizeof(int));
3242 break;
3243 case SNDCTL_DSP_GETOSPACE:
3244 case SNDCTL_DSP_GETISPACE:
3245 SYSCALL_TRACK( pre_mem_write,tid,
3246 "ioctl(SNDCTL_XXX|SOUND_XXX "
3247 "(SIOR, audio_buf_info))", arg3,
3248 sizeof(audio_buf_info));
3249 break;
3250 case SNDCTL_DSP_SETTRIGGER:
3251 SYSCALL_TRACK( pre_mem_read,tid,
3252 "ioctl(SNDCTL_XXX|SOUND_XXX (SIOW, int))",
3253 arg3, sizeof(int));
3254 break;
3255
3256 case SNDCTL_DSP_POST:
3257 case SNDCTL_DSP_RESET:
3258 case SNDCTL_DSP_SYNC:
3259 case SNDCTL_DSP_SETSYNCRO:
3260 case SNDCTL_DSP_SETDUPLEX:
3261 break;
3262
3263 /* Real Time Clock (/dev/rtc) ioctls */
3264# ifndef GLIBC_2_1
3265 case RTC_UIE_ON:
3266 case RTC_UIE_OFF:
3267 case RTC_AIE_ON:
3268 case RTC_AIE_OFF:
3269 case RTC_PIE_ON:
3270 case RTC_PIE_OFF:
3271 case RTC_IRQP_SET:
3272 break;
3273 case RTC_RD_TIME:
3274 case RTC_ALM_READ:
3275 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(RTC_RD_TIME/ALM_READ)",
3276 arg3, sizeof(struct rtc_time));
3277 break;
3278 case RTC_ALM_SET:
3279 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(RTC_ALM_SET)", arg3,
3280 sizeof(struct rtc_time));
3281 break;
3282 case RTC_IRQP_READ:
3283 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(RTC_IRQP_READ)", arg3,
3284 sizeof(unsigned long));
3285 break;
3286# endif /* GLIBC_2_1 */
3287
3288# ifdef BLKGETSIZE
3289 case BLKGETSIZE:
3290 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(BLKGETSIZE)", arg3,
3291 sizeof(unsigned long));
3292 break;
3293# endif /* BLKGETSIZE */
3294
thughesacbbc322004-06-19 12:12:01 +00003295 /* Hard disks */
3296 case HDIO_GET_IDENTITY: /* 0x030d */
3297 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(HDIO_GET_IDENTITY)", arg3,
3298 sizeof(struct hd_driveid) );
3299 break;
3300
jsgf855d93d2003-10-13 22:26:55 +00003301 /* CD ROM stuff (??) */
nethercote671398c2004-02-22 18:08:04 +00003302 case CDROM_GET_MCN:
3303 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(CDROM_GET_MCN)", arg3,
3304 sizeof(struct cdrom_mcn) );
3305 break;
3306 case CDROM_SEND_PACKET:
3307 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(CDROM_SEND_PACKET)", arg3,
3308 sizeof(struct cdrom_generic_command));
3309 break;
jsgf855d93d2003-10-13 22:26:55 +00003310 case CDROMSUBCHNL:
3311 SYSCALL_TRACK( pre_mem_read,tid,
3312 "ioctl(CDROMSUBCHNL (cdsc_format, char))",
3313 (int) &(((struct cdrom_subchnl *) arg3)->cdsc_format),
3314 sizeof(((struct cdrom_subchnl *) arg3)->cdsc_format));
3315 SYSCALL_TRACK( pre_mem_write,tid,
3316 "ioctl(CDROMSUBCHNL)", arg3,
3317 sizeof(struct cdrom_subchnl));
3318 break;
nethercote671398c2004-02-22 18:08:04 +00003319 case CDROMREADMODE2:
3320 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(CDROMREADMODE2)", arg3,
3321 CD_FRAMESIZE_RAW0 );
3322 break;
jsgf855d93d2003-10-13 22:26:55 +00003323 case CDROMREADTOCHDR:
3324 SYSCALL_TRACK( pre_mem_write,tid,
3325 "ioctl(CDROMREADTOCHDR)", arg3,
3326 sizeof(struct cdrom_tochdr));
3327 break;
3328 case CDROMREADTOCENTRY:
3329 SYSCALL_TRACK( pre_mem_read,tid,
3330 "ioctl(CDROMREADTOCENTRY (cdte_format, char))",
3331 (int) &(((struct cdrom_tocentry *) arg3)->cdte_format),
3332 sizeof(((struct cdrom_tocentry *) arg3)->cdte_format));
3333 SYSCALL_TRACK( pre_mem_read,tid,
3334 "ioctl(CDROMREADTOCENTRY (cdte_track, char))",
3335 (int) &(((struct cdrom_tocentry *) arg3)->cdte_track),
3336 sizeof(((struct cdrom_tocentry *) arg3)->cdte_track));
3337 SYSCALL_TRACK( pre_mem_write,tid,
3338 "ioctl(CDROMREADTOCENTRY)", arg3,
3339 sizeof(struct cdrom_tocentry));
3340 break;
3341 case CDROMPLAYMSF:
3342 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(CDROMPLAYMSF)", arg3,
3343 sizeof(struct cdrom_msf));
3344 break;
3345 /* The following two are probably bogus (should check args
3346 for readability). JRS 20021117 */
3347 case CDROM_DRIVE_STATUS: /* 0x5326 */
3348 case CDROM_CLEAR_OPTIONS: /* 0x5321 */
3349 break;
thughes66d80092004-06-19 12:41:05 +00003350
3351 case FIGETBSZ:
3352 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(FIGETBSZ)", arg3,
3353 sizeof(unsigned long));
3354 break;
3355 case FIBMAP:
3356 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(FIBMAP)", arg3,
3357 sizeof(unsigned long));
3358 break;
3359
thughes1742d6f2004-04-22 07:28:43 +00003360#ifdef HAVE_LINUX_FB_H
thughes44e35582004-04-21 15:52:33 +00003361 case FBIOGET_VSCREENINFO: /* 0x4600 */
3362 SYSCALL_TRACK( pre_mem_write,tid,
3363 "ioctl(FBIOGET_VSCREENINFO)", arg3,
3364 sizeof(struct fb_var_screeninfo));
3365 break;
3366 case FBIOGET_FSCREENINFO: /* 0x4602 */
3367 SYSCALL_TRACK( pre_mem_write,tid,
3368 "ioctl(FBIOGET_FSCREENINFO)", arg3,
3369 sizeof(struct fb_fix_screeninfo));
3370 break;
thughes1742d6f2004-04-22 07:28:43 +00003371#endif
jsgf855d93d2003-10-13 22:26:55 +00003372
3373 /* We don't have any specific information on it, so
3374 try to do something reasonable based on direction and
3375 size bits. The encoding scheme is described in
3376 /usr/include/asm/ioctl.h.
3377
3378 According to Simon Hausmann, _IOC_READ means the kernel
3379 writes a value to the ioctl value passed from the user
3380 space and the other way around with _IOC_WRITE. */
3381 default: {
3382 UInt dir = _IOC_DIR(arg2);
3383 UInt size = _IOC_SIZE(arg2);
3384 if (VG_(strstr)(VG_(clo_weird_hacks), "lax-ioctls") != NULL) {
3385 /*
3386 * Be very lax about ioctl handling; the only
3387 * assumption is that the size is correct. Doesn't
3388 * require the full buffer to be initialized when
3389 * writing. Without this, using some device
3390 * drivers with a large number of strange ioctl
3391 * commands becomes very tiresome.
3392 */
3393 } else if (/* size == 0 || */ dir == _IOC_NONE) {
3394 static Int moans = 3;
3395 if (moans > 0) {
3396 moans--;
3397 VG_(message)(Vg_UserMsg,
3398 "Warning: noted but unhandled ioctl 0x%x"
3399 " with no size/direction hints",
3400 arg2);
3401 VG_(message)(Vg_UserMsg,
3402 " This could cause spurious value errors"
3403 " to appear.");
3404 VG_(message)(Vg_UserMsg,
3405 " See README_MISSING_SYSCALL_OR_IOCTL for "
3406 "guidance on writing a proper wrapper." );
3407 }
3408 } else {
3409 if ((dir & _IOC_WRITE) && size > 0)
3410 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(generic)",
3411 arg3, size);
3412 if ((dir & _IOC_READ) && size > 0)
3413 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(generic)",
3414 arg3, size);
3415 }
3416 break;
3417 }
3418 }
3419}
3420
3421POST(ioctl)
3422{
3423 /* int ioctl(int d, int request, ...)
3424 [The "third" argument is traditionally char *argp,
3425 and will be so named for this discussion.]
3426 */
3427 /*
3428 VG_(message)(
3429 Vg_DebugMsg,
3430 "is an IOCTL, request = 0x%x, d = %d, argp = 0x%x",
3431 arg2,arg1,arg3);
3432 */
3433 MAYBE_PRINTF("ioctl ( %d, 0x%x, %p )\n",arg1,arg2,arg3);
3434 switch (arg2 /* request */) {
3435 case TCSETS:
3436 case TCSETSW:
3437 case TCSETSF:
3438 break;
3439 case TCGETS:
3440 if (res == 0)
3441 VG_TRACK( post_mem_write, arg3, VKI_SIZEOF_STRUCT_TERMIOS );
3442 break;
3443 case TCSETA:
3444 case TCSETAW:
3445 case TCSETAF:
3446 break;
3447 case TCGETA:
3448 if (res == 0)
3449 VG_TRACK( post_mem_write, arg3, VKI_SIZEOF_STRUCT_TERMIO );
3450 break;
3451 case TCSBRK:
3452 case TCXONC:
3453 case TCSBRKP:
3454 case TCFLSH:
3455 break;
3456 case TIOCGWINSZ:
3457 if (res == 0)
3458 VG_TRACK( post_mem_write, arg3, sizeof(struct winsize) );
3459 break;
3460 case TIOCSWINSZ:
3461 break;
3462 case TIOCLINUX:
3463 if (res == 0)
3464 VG_TRACK( post_mem_write, arg3, sizeof(char *) );
3465 break;
3466 case TIOCGPGRP:
3467 /* Get process group ID for foreground processing group. */
3468 if (res == 0)
3469 VG_TRACK( post_mem_write, arg3, sizeof(pid_t) );
3470 break;
3471 case TIOCSPGRP:
3472 /* Set a process group ID? */
3473 if (res == 0)
3474 VG_TRACK( post_mem_write, arg3, sizeof(pid_t) );
3475 break;
3476 case TIOCGPTN: /* Get Pty Number (of pty-mux device) */
3477 if (res == 0)
3478 VG_TRACK( post_mem_write, arg3, sizeof(int));
3479 break;
3480 case TIOCSCTTY:
3481 break;
3482 case TIOCSPTLCK: /* Lock/unlock Pty */
3483 break;
3484 case FIONBIO:
3485 break;
3486 case FIOASYNC:
3487 break;
3488 case FIONREAD: /* identical to SIOCINQ */
3489 if (res == 0)
3490 VG_TRACK( post_mem_write, arg3, sizeof(int) );
3491 break;
3492
3493 /* If you get compilation problems here, change the #if
3494 1 to #if 0 and get rid of <scsi/sg.h> in
3495 vg_unsafe.h. */
3496# if 1
3497 case SG_SET_COMMAND_Q:
3498 break;
3499# if defined(SG_IO)
3500 case SG_IO:
3501 if (res == 0)
3502 VG_TRACK( post_mem_write,arg3, sizeof(struct sg_io_hdr));
3503 break;
3504# endif /* SG_IO */
3505 case SG_GET_SCSI_ID:
3506 if (res == 0)
3507 VG_TRACK( post_mem_write,arg3, sizeof(struct sg_scsi_id));
3508 break;
3509 case SG_SET_RESERVED_SIZE:
3510 break;
3511 case SG_SET_TIMEOUT:
3512 break;
3513 case SG_GET_RESERVED_SIZE:
3514 if (res == 0)
3515 VG_TRACK( post_mem_write,arg3, sizeof(int));
3516 break;
3517 case SG_GET_TIMEOUT:
3518 if (res == 0)
3519 VG_TRACK( post_mem_write,arg3, sizeof(int));
3520 break;
3521 case SG_GET_VERSION_NUM:
3522 break;
3523# endif
3524
muellera4b153a2003-11-19 22:07:14 +00003525 case VKI_IIOCGETCPS:
jsgf855d93d2003-10-13 22:26:55 +00003526 /* In early 2.4 kernels, ISDN_MAX_CHANNELS was only defined
3527 * when KERNEL was. I never saw a larger value than 64 though */
3528# ifndef ISDN_MAX_CHANNELS
3529# define ISDN_MAX_CHANNELS 64
3530# endif
3531 if (res == 0)
3532 VG_TRACK( post_mem_write, arg3, ISDN_MAX_CHANNELS
3533 * 2 * sizeof(unsigned long) );
3534 break;
muellera4b153a2003-11-19 22:07:14 +00003535 case VKI_IIOCNETGPN:
jsgf855d93d2003-10-13 22:26:55 +00003536 if (res == 0)
3537 VG_TRACK( post_mem_write, arg3, sizeof(isdn_net_ioctl_phone) );
3538 break;
3539
3540 /* These all use struct ifreq AFAIK */
thughesbe811712004-06-17 23:04:58 +00003541 case SIOCGIFINDEX: /* get iface index */
3542 if (res == 0)
3543 VG_TRACK( post_mem_write,
3544 (UInt)&((struct ifreq *)arg3)->ifr_ifindex,
3545 sizeof(((struct ifreq *)arg3)->ifr_ifindex) );
3546 break;
jsgf855d93d2003-10-13 22:26:55 +00003547 case SIOCGIFFLAGS: /* get flags */
thughesbe811712004-06-17 23:04:58 +00003548 if (res == 0)
3549 VG_TRACK( post_mem_write,
3550 (UInt)&((struct ifreq *)arg3)->ifr_flags,
3551 sizeof(((struct ifreq *)arg3)->ifr_flags) );
3552 break;
jsgf855d93d2003-10-13 22:26:55 +00003553 case SIOCGIFHWADDR: /* Get hardware address */
thughesbe811712004-06-17 23:04:58 +00003554 if (res == 0)
3555 VG_TRACK( post_mem_write,
3556 (UInt)&((struct ifreq *)arg3)->ifr_hwaddr,
3557 sizeof(((struct ifreq *)arg3)->ifr_hwaddr) );
3558 break;
jsgf855d93d2003-10-13 22:26:55 +00003559 case SIOCGIFMTU: /* get MTU size */
thughesbe811712004-06-17 23:04:58 +00003560 if (res == 0)
3561 VG_TRACK( post_mem_write,
3562 (UInt)&((struct ifreq *)arg3)->ifr_mtu,
3563 sizeof(((struct ifreq *)arg3)->ifr_mtu) );
3564 break;
jsgf855d93d2003-10-13 22:26:55 +00003565 case SIOCGIFADDR: /* get PA address */
jsgf855d93d2003-10-13 22:26:55 +00003566 case SIOCGIFDSTADDR: /* get remote PA address */
3567 case SIOCGIFBRDADDR: /* get broadcast PA address */
thughesbe811712004-06-17 23:04:58 +00003568 case SIOCGIFNETMASK: /* get network PA mask */
3569 if (res == 0)
3570 VG_TRACK( post_mem_write,
3571 (UInt)&((struct ifreq *)arg3)->ifr_addr,
3572 sizeof(((struct ifreq *)arg3)->ifr_addr) );
3573 break;
3574 case SIOCGIFMETRIC: /* get metric */
3575 if (res == 0)
3576 VG_TRACK( post_mem_write,
3577 (UInt)&((struct ifreq *)arg3)->ifr_metric,
3578 sizeof(((struct ifreq *)arg3)->ifr_metric) );
3579 break;
3580 case SIOCGIFMAP: /* Get device parameters */
3581 if (res == 0)
3582 VG_TRACK( post_mem_write,
3583 (UInt)&((struct ifreq *)arg3)->ifr_map,
3584 sizeof(((struct ifreq *)arg3)->ifr_map) );
3585 break;
3586 break;
3587 case SIOCGIFTXQLEN: /* Get the tx queue length */
3588 if (res == 0)
3589 VG_TRACK( post_mem_write,
3590 (UInt)&((struct ifreq *)arg3)->ifr_qlen,
3591 sizeof(((struct ifreq *)arg3)->ifr_qlen) );
3592 break;
jsgf855d93d2003-10-13 22:26:55 +00003593 case SIOCGIFNAME: /* get iface name */
3594 if (res == 0)
thughesbe811712004-06-17 23:04:58 +00003595 VG_TRACK( post_mem_write,
3596 (UInt)&((struct ifreq *)arg3)->ifr_name,
3597 sizeof(((struct ifreq *)arg3)->ifr_name) );
jsgf855d93d2003-10-13 22:26:55 +00003598 break;
thughesbe811712004-06-17 23:04:58 +00003599#ifdef HAVE_LINUX_MII_H
3600 case SIOCGMIIPHY: /* get hardware entry */
3601 if (res == 0)
3602 VG_TRACK( post_mem_write,
3603 (UInt)&((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->phy_id,
3604 sizeof(((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->phy_id) );
3605 break;
3606 case SIOCGMIIREG: /* get hardware entry registers */
3607 if (res == 0)
3608 VG_TRACK( post_mem_write,
3609 (UInt)&((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->val_out,
3610 sizeof(((struct mii_ioctl_data *)&((struct ifreq *)arg3)->ifr_data)->val_out) );
3611 break;
3612#endif
jsgf855d93d2003-10-13 22:26:55 +00003613 case SIOCGIFCONF: /* get iface list */
3614 /* WAS:
3615 SYSCALL_TRACK( pre_mem_write,"ioctl(SIOCGIFCONF)", arg3,
3616 sizeof(struct ifconf));
3617 KERNEL_DO_SYSCALL(tid,res);
3618 if (!VG_(is_kerror)(res) && res == 0)
3619 VG_TRACK( post_mem_write,arg3, sizeof(struct ifconf));
3620 */
3621 if (res == 0 && arg3 ) {
3622 struct ifconf *ifc = (struct ifconf *) arg3;
3623 if (ifc->ifc_buf != NULL)
3624 VG_TRACK( post_mem_write, (Addr)(ifc->ifc_buf),
3625 (UInt)(ifc->ifc_len) );
3626 }
3627 break;
3628 case SIOCGSTAMP:
3629 if (res == 0)
3630 VG_TRACK( post_mem_write,arg3, sizeof(struct timeval));
3631 break;
3632 /* SIOCOUTQ is an ioctl that, when called on a socket, returns
3633 the number of bytes currently in that socket's send buffer.
3634 It writes this value as an int to the memory location
3635 indicated by the third argument of ioctl(2). */
3636 case SIOCOUTQ:
3637 if (res == 0)
3638 VG_TRACK( post_mem_write,arg3, sizeof(int));
3639 break;
3640 case SIOCGRARP: /* get RARP table entry */
3641 case SIOCGARP: /* get ARP table entry */
3642 if (res == 0)
3643 VG_TRACK( post_mem_write,arg3, sizeof(struct arpreq));
3644 break;
3645
3646 case SIOCSIFFLAGS: /* set flags */
3647 case SIOCSIFMAP: /* Set device parameters */
3648 case SIOCSIFTXQLEN: /* Set the tx queue length */
3649 case SIOCSIFDSTADDR: /* set remote PA address */
3650 case SIOCSIFBRDADDR: /* set broadcast PA address */
3651 case SIOCSIFNETMASK: /* set network PA mask */
3652 case SIOCSIFMETRIC: /* set metric */
3653 case SIOCSIFADDR: /* set PA address */
3654 case SIOCSIFMTU: /* set MTU size */
3655 case SIOCSIFHWADDR: /* set hardware address */
thughesbe811712004-06-17 23:04:58 +00003656#ifdef HAVE_LINUX_MII_H
3657 case SIOCSMIIREG: /* set hardware entry registers */
3658#endif
jsgf855d93d2003-10-13 22:26:55 +00003659 break;
3660 /* Routing table calls. */
3661 case SIOCADDRT: /* add routing table entry */
3662 case SIOCDELRT: /* delete routing table entry */
3663 break;
3664
3665 /* RARP cache control calls. */
3666 case SIOCDRARP: /* delete RARP table entry */
3667 case SIOCSRARP: /* set RARP table entry */
3668 /* ARP cache control calls. */
3669 case SIOCSARP: /* set ARP table entry */
3670 case SIOCDARP: /* delete ARP table entry */
3671 break;
3672
3673 case SIOCSPGRP:
3674 break;
3675
3676 /* linux/soundcard interface (OSS) */
3677 case SNDCTL_SEQ_GETOUTCOUNT:
3678 case SNDCTL_SEQ_GETINCOUNT:
3679 case SNDCTL_SEQ_PERCMODE:
3680 case SNDCTL_SEQ_TESTMIDI:
3681 case SNDCTL_SEQ_RESETSAMPLES:
3682 case SNDCTL_SEQ_NRSYNTHS:
3683 case SNDCTL_SEQ_NRMIDIS:
3684 case SNDCTL_SEQ_GETTIME:
3685 case SNDCTL_DSP_GETFMTS:
3686 case SNDCTL_DSP_GETTRIGGER:
3687 case SNDCTL_DSP_GETODELAY:
3688# if defined(SNDCTL_DSP_GETSPDIF)
3689 case SNDCTL_DSP_GETSPDIF:
3690# endif
3691 case SNDCTL_DSP_GETCAPS:
3692 case SOUND_PCM_READ_RATE:
3693 case SOUND_PCM_READ_CHANNELS:
3694 case SOUND_PCM_READ_BITS:
3695 case (SOUND_PCM_READ_BITS|0x40000000): /* what the fuck ? */
3696 case SOUND_PCM_READ_FILTER:
3697 if (res == 0)
3698 VG_TRACK( post_mem_write,arg3, sizeof(int));
3699 break;
3700 case SNDCTL_SEQ_CTRLRATE:
3701 case SNDCTL_DSP_SPEED:
3702 case SNDCTL_DSP_STEREO:
3703 case SNDCTL_DSP_GETBLKSIZE:
3704 case SNDCTL_DSP_CHANNELS:
3705 case SOUND_PCM_WRITE_FILTER:
3706 case SNDCTL_DSP_SUBDIVIDE:
3707 case SNDCTL_DSP_SETFRAGMENT:
3708# if defined(SNDCTL_DSP_GETCHANNELMASK)
3709 case SNDCTL_DSP_GETCHANNELMASK:
3710# endif
3711# if defined(SNDCTL_DSP_BIND_CHANNEL)
3712 case SNDCTL_DSP_BIND_CHANNEL:
3713# endif
3714 case SNDCTL_TMR_TIMEBASE:
3715 case SNDCTL_TMR_TEMPO:
3716 case SNDCTL_TMR_SOURCE:
3717 case SNDCTL_MIDI_PRETIME:
3718 case SNDCTL_MIDI_MPUMODE:
3719 break;
3720 case SNDCTL_DSP_GETOSPACE:
3721 case SNDCTL_DSP_GETISPACE:
3722 if (res == 0)
3723 VG_TRACK( post_mem_write,arg3, sizeof(audio_buf_info));
3724 break;
3725 case SNDCTL_DSP_SETTRIGGER:
3726 break;
3727
3728 case SNDCTL_DSP_POST:
3729 case SNDCTL_DSP_RESET:
3730 case SNDCTL_DSP_SYNC:
3731 case SNDCTL_DSP_SETSYNCRO:
3732 case SNDCTL_DSP_SETDUPLEX:
3733 break;
3734
3735 /* Real Time Clock (/dev/rtc) ioctls */
3736# ifndef GLIBC_2_1
3737 case RTC_UIE_ON:
3738 case RTC_UIE_OFF:
3739 case RTC_AIE_ON:
3740 case RTC_AIE_OFF:
3741 case RTC_PIE_ON:
3742 case RTC_PIE_OFF:
3743 case RTC_IRQP_SET:
3744 break;
3745 case RTC_RD_TIME:
3746 case RTC_ALM_READ:
3747 if (res == 0)
3748 VG_TRACK( post_mem_write,arg3, sizeof(struct rtc_time));
3749 break;
3750 case RTC_ALM_SET:
3751 break;
3752 case RTC_IRQP_READ:
3753 if(res == 0)
3754 VG_TRACK( post_mem_write,arg3, sizeof(unsigned long));
3755 break;
3756# endif /* GLIBC_2_1 */
3757
3758# ifdef BLKGETSIZE
3759 case BLKGETSIZE:
3760 if (res == 0)
3761 VG_TRACK( post_mem_write,arg3, sizeof(unsigned long));
3762 break;
3763# endif /* BLKGETSIZE */
3764
thughesacbbc322004-06-19 12:12:01 +00003765 /* Hard disks */
3766 case HDIO_GET_IDENTITY: /* 0x030d */
3767 if (res == 0)
3768 VG_TRACK( post_mem_write,arg3, sizeof(struct hd_driveid));
3769 break;
3770
jsgf855d93d2003-10-13 22:26:55 +00003771 /* CD ROM stuff (??) */
3772 case CDROMSUBCHNL:
3773 if (res == 0)
3774 VG_TRACK( post_mem_write,arg3, sizeof(struct cdrom_subchnl));
3775 break;
3776 case CDROMREADTOCHDR:
3777 if (res == 0)
3778 VG_TRACK( post_mem_write,arg3, sizeof(struct cdrom_tochdr));
3779 break;
3780 case CDROMREADTOCENTRY:
3781 if (res == 0)
3782 VG_TRACK( post_mem_write,arg3, sizeof(struct cdrom_tochdr));
3783 break;
3784 case CDROMPLAYMSF:
3785 break;
3786 /* The following two are probably bogus (should check args
3787 for readability). JRS 20021117 */
3788 case CDROM_DRIVE_STATUS: /* 0x5326 */
3789 case CDROM_CLEAR_OPTIONS: /* 0x5321 */
3790 break;
3791
thughes66d80092004-06-19 12:41:05 +00003792 case FIGETBSZ:
3793 if (res == 0)
3794 VG_TRACK( post_mem_write,arg3, sizeof(unsigned long));
3795 break;
3796 case FIBMAP:
3797 if (res == 0)
3798 VG_TRACK( post_mem_write,arg3, sizeof(unsigned long));
3799 break;
3800
thughes1742d6f2004-04-22 07:28:43 +00003801#ifdef HAVE_LINUX_FB_H
thughes44e35582004-04-21 15:52:33 +00003802 case FBIOGET_VSCREENINFO: //0x4600
3803 if (res == 0)
3804 VG_TRACK( post_mem_write,arg3, sizeof(struct fb_var_screeninfo));
3805 break;
3806 case FBIOGET_FSCREENINFO: //0x4602
3807 if (res == 0)
3808 VG_TRACK( post_mem_write,arg3, sizeof(struct fb_fix_screeninfo));
3809 break;
thughes1742d6f2004-04-22 07:28:43 +00003810#endif
thughes44e35582004-04-21 15:52:33 +00003811
jsgf855d93d2003-10-13 22:26:55 +00003812 /* We don't have any specific information on it, so
3813 try to do something reasonable based on direction and
3814 size bits. The encoding scheme is described in
3815 /usr/include/asm/ioctl.h.
3816
3817 According to Simon Hausmann, _IOC_READ means the kernel
3818 writes a value to the ioctl value passed from the user
3819 space and the other way around with _IOC_WRITE. */
3820 default: {
3821 UInt dir = _IOC_DIR(arg2);
3822 UInt size = _IOC_SIZE(arg2);
3823 if (size > 0 && (dir & _IOC_READ)
3824 && res == 0
3825 && arg3 != (Addr)NULL)
3826 VG_TRACK( post_mem_write,arg3, size);
3827 break;
3828 }
3829 }
3830}
3831
3832PRE(kill)
3833{
3834 /* int kill(pid_t pid, int sig); */
3835 MAYBE_PRINTF("kill ( %d, %d )\n", arg1,arg2);
3836 if (arg2 == VKI_SIGVGINT || arg2 == VKI_SIGVGKILL)
3837 res = -VKI_EINVAL;
3838}
3839
3840POST(kill)
3841{
3842 /* If this was a self-kill then wait for a signal to be
3843 delivered to any thread before claiming the kill is done. */
3844 if (res >= 0 && /* if it was successful */
3845 arg2 != 0 && /* if a real signal */
3846 !VG_(is_sig_ign)(arg2) && /* that isn't ignored and */
3847 !VG_(ksigismember)(&tst->eff_sig_mask, arg2) && /* we're not blocking it */
3848 (arg1 == VG_(getpid)() || /* directed at us or */
3849 arg1 == -1 || /* directed at everyone or */
3850 arg1 == 0 || /* directed at whole group or */
3851 -arg1 == VG_(getpgrp)())) { /* directed at our group... */
3852 /* ...then wait for that signal to be delivered to someone
3853 (might be us, might be someone else who doesn't have it
3854 blocked) */
3855 VG_(proxy_waitsig)();
3856 }
3857}
3858
3859PRE(link)
3860{
3861 /* int link(const char *oldpath, const char *newpath); */
3862 MAYBE_PRINTF("link ( %p, %p)\n", arg1, arg2);
3863 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "link(oldpath)", arg1);
3864 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "link(newpath)", arg2);
3865}
3866
3867PRE(lseek)
3868{
3869 /* off_t lseek(int fildes, off_t offset, int whence); */
3870 MAYBE_PRINTF("lseek ( %d, %d, %d )\n",arg1,arg2,arg3);
3871}
3872
3873PRE(_llseek)
3874{
3875 /* int _llseek(unsigned int fd, unsigned long offset_high,
3876 unsigned long offset_low,
3877 loff_t * result, unsigned int whence); */
3878 MAYBE_PRINTF("llseek ( %d, 0x%x, 0x%x, %p, %d )\n",
3879 arg1,arg2,arg3,arg4,arg5);
3880 SYSCALL_TRACK( pre_mem_write, tid, "llseek(result)", arg4,
3881 sizeof(loff_t));
3882}
3883
3884POST(_llseek)
3885{
3886 if (res == 0)
3887 VG_TRACK( post_mem_write, arg4, sizeof(loff_t) );
3888}
3889
3890PRE(lstat)
3891{
3892 /* int lstat(const char *file_name, struct stat *buf); */
fitzhardinge98abfc72003-12-16 02:05:15 +00003893 MAYBE_PRINTF("lstat ( %p \"%s\", %p )\n",arg1,arg1,arg2);
jsgf855d93d2003-10-13 22:26:55 +00003894 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "lstat(file_name)", arg1 );
3895 SYSCALL_TRACK( pre_mem_write, tid, "lstat(buf)", arg2,
3896 sizeof(struct stat) );
3897}
3898
3899POST(lstat)
3900{
3901 if (res == 0) {
3902 VG_TRACK( post_mem_write, arg2, sizeof(struct stat) );
3903 }
3904}
3905
3906PRE(lstat64)
3907{
3908 /* int lstat64(const char *file_name, struct stat64 *buf); */
fitzhardinge98abfc72003-12-16 02:05:15 +00003909 MAYBE_PRINTF("lstat64 ( %p \"%s\", %p )\n",arg1,arg1,arg2);
jsgf855d93d2003-10-13 22:26:55 +00003910 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "lstat64(file_name)", arg1 );
3911 SYSCALL_TRACK( pre_mem_write, tid, "lstat64(buf)", arg2,
3912 sizeof(struct stat64) );
3913}
3914
3915POST(lstat64)
3916{
3917 if (res == 0) {
3918 VG_TRACK( post_mem_write, arg2, sizeof(struct stat64) );
3919 }
3920}
3921
3922PRE(mkdir)
3923{
3924 /* int mkdir(const char *pathname, mode_t mode); */
3925 MAYBE_PRINTF("mkdir ( %p, %d )\n", arg1,arg2);
3926 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "mkdir(pathname)", arg1 );
3927}
3928
3929PRE(mmap2)
3930{
nethercote27ea8bc2004-07-10 17:21:14 +00003931 // Exactly like __NR_mmap except:
3932 // - all 6 args are passed in regs, rather than in a memory-block.
3933 // - the file offset is specified in pagesize units rather than bytes,
3934 // so that it can be used for files bigger than 2^32 bytes.
jsgf855d93d2003-10-13 22:26:55 +00003935 /* void* mmap(void *start, size_t length, int prot,
3936 int flags, int fd, off_t offset);
3937 */
3938 MAYBE_PRINTF("mmap2 ( %p, %d, %d, %d, %d, %d )\n",
3939 arg1, arg2, arg3, arg4, arg5, arg6 );
nethercotedb233322003-12-02 14:56:04 +00003940
fitzhardinge98abfc72003-12-16 02:05:15 +00003941 if (arg4 & VKI_MAP_FIXED) {
3942 if (!valid_client_addr(arg1, arg2, tid, "mmap2"))
3943 res = -VKI_ENOMEM;
3944 } else {
3945 arg1 = VG_(find_map_space)(arg1, arg2, True);
fitzhardinge98abfc72003-12-16 02:05:15 +00003946 if (arg1 == 0)
3947 res = -VKI_ENOMEM;
nethercote27ea8bc2004-07-10 17:21:14 +00003948 else
3949 arg4 |= VKI_MAP_FIXED;
fitzhardinge98abfc72003-12-16 02:05:15 +00003950 }
jsgf855d93d2003-10-13 22:26:55 +00003951}
3952
3953POST(mmap2)
3954{
nethercotefe082612004-07-10 18:08:13 +00003955 vg_assert(valid_client_addr(res, arg2, tid, "mmap2"));
3956 mmap_segment( (Addr)res, arg2, arg3, arg4, arg5, arg6 * (ULong)VKI_BYTES_PER_PAGE );
jsgf855d93d2003-10-13 22:26:55 +00003957}
3958
3959PRE(mmap)
3960{
3961 /* void* mmap(void *start, size_t length, int prot,
3962 int flags, int fd, off_t offset);
3963 */
3964
3965 UInt* arg_block = (UInt*)arg1;
3966 UInt a1, a2, a3, a4, a5, a6;
3967
3968 SYSCALL_TRACK( pre_mem_read, tid, "mmap(args)", arg1, 6*sizeof(UInt) );
3969
3970 a1 = arg_block[0];
3971 a2 = arg_block[1];
3972 a3 = arg_block[2];
3973 a4 = arg_block[3];
3974 a5 = arg_block[4];
3975 a6 = arg_block[5];
3976 MAYBE_PRINTF("mmap ( %p, %d, %d, %d, %d, %d )\n",
3977 a1, a2, a3, a4, a5, a6 );
nethercotedb233322003-12-02 14:56:04 +00003978
fitzhardinge98abfc72003-12-16 02:05:15 +00003979 if (a4 & VKI_MAP_FIXED) {
3980 if (!valid_client_addr(a1, a2, tid, "mmap")) {
3981 MAYBE_PRINTF("mmap failing: %p-%p\n", a1, a1+a2);
3982 res = -VKI_ENOMEM;
3983 }
3984 } else {
3985 a1 = VG_(find_map_space)(arg_block[0], arg_block[1], True);
3986 if (a1 == 0)
3987 res = -VKI_ENOMEM;
3988 else
3989 a4 |= VKI_MAP_FIXED;
3990 }
jsgf855d93d2003-10-13 22:26:55 +00003991
fitzhardinge98abfc72003-12-16 02:05:15 +00003992 if (res != -VKI_ENOMEM) {
fitzhardingec2d65072004-01-07 08:44:43 +00003993 UInt new_arg_block[6];
3994
3995 new_arg_block[0] = a1;
3996 new_arg_block[1] = a2;
3997 new_arg_block[2] = a3;
3998 new_arg_block[3] = a4;
3999 new_arg_block[4] = a5;
4000 new_arg_block[5] = a6;
fitzhardinge98abfc72003-12-16 02:05:15 +00004001
fitzhardingec2d65072004-01-07 08:44:43 +00004002 res = VG_(do_syscall)(__NR_mmap, new_arg_block);
4003
4004 if (!VG_(is_kerror)(res)) {
nethercoteb4250ae2004-07-10 16:50:09 +00004005 vg_assert(valid_client_addr(res, a2, tid, "mmap"));
4006 mmap_segment( (Addr)res, a2, a3, a4, a5, a6 );
fitzhardingec2d65072004-01-07 08:44:43 +00004007 }
fitzhardinge98abfc72003-12-16 02:05:15 +00004008 }
jsgf855d93d2003-10-13 22:26:55 +00004009}
4010
4011PRE(mprotect)
4012{
4013 /* int mprotect(const void *addr, size_t len, int prot); */
4014 /* should addr .. addr+len-1 be checked before the call? */
4015 MAYBE_PRINTF("mprotect ( %p, %d, %d )\n", arg1,arg2,arg3);
fitzhardinge98abfc72003-12-16 02:05:15 +00004016
4017 if (!valid_client_addr(arg1, arg2, tid, "mprotect"))
4018 res = -VKI_ENOMEM;
jsgf855d93d2003-10-13 22:26:55 +00004019}
4020
4021POST(mprotect)
4022{
nethercote27ea8bc2004-07-10 17:21:14 +00004023 Addr a = arg1;
4024 UInt len = arg2;
4025 Int prot = arg3;
4026 Bool rr = prot & VKI_PROT_READ;
4027 Bool ww = prot & VKI_PROT_WRITE;
4028 Bool xx = prot & VKI_PROT_EXEC;
4029
nethercote27ea8bc2004-07-10 17:21:14 +00004030 mash_addr_and_len(&a, &len);
4031 VG_(mprotect_range)(a, len, prot);
4032 VG_TRACK( change_mem_mprotect, a, len, rr, ww, xx );
jsgf855d93d2003-10-13 22:26:55 +00004033}
4034
4035PRE(munmap)
4036{
4037 /* int munmap(void *start, size_t length); */
4038 /* should start .. start+length-1 be checked before the call? */
4039 MAYBE_PRINTF("munmap ( %p, %d )\n", arg1,arg2);
fitzhardinge98abfc72003-12-16 02:05:15 +00004040
4041 if (!valid_client_addr(arg1, arg2, tid, "munmap"))
4042 res = -VKI_EINVAL;
jsgf855d93d2003-10-13 22:26:55 +00004043}
4044
4045POST(munmap)
4046{
nethercote27ea8bc2004-07-10 17:21:14 +00004047 Addr a = arg1;
4048 UInt len = arg2;
4049
4050 mash_addr_and_len(&a, &len);
4051 VG_(unmap_range)(a, len);
4052 VG_TRACK( die_mem_munmap, a, len );
jsgf855d93d2003-10-13 22:26:55 +00004053}
4054
mueller6ceb2312004-01-02 22:52:34 +00004055PRE(mincore)
4056{
4057 /* int mincore(void *start, size_t length, unsigned char *vec); */
4058 MAYBE_PRINTF("mincore ( %p, %d, %p )\n", arg1,arg2,arg3);
4059 SYSCALL_TRACK(pre_mem_write, tid, "mincore(vec)",
4060 arg3, (arg2 + 4096 - 1) / 4096);
4061}
4062
4063POST(mincore)
4064{
nethercotefe082612004-07-10 18:08:13 +00004065 VG_TRACK( post_mem_write, arg3, (arg2 + 4096 - 1) / 4096 );
mueller6ceb2312004-01-02 22:52:34 +00004066}
4067
jsgf855d93d2003-10-13 22:26:55 +00004068PRE(nanosleep)
4069{
nethercotefe082612004-07-10 18:08:13 +00004070 /* int nanosleep(const struct timespec *req, struct timespec *rem); */
4071 MAYBE_PRINTF("nanosleep ( %p, %p )\n", arg1,arg2);
4072 SYSCALL_TRACK( pre_mem_read, tid, "nanosleep(req)", arg1,
4073 sizeof(struct timespec) );
4074 if (arg2 != (UInt)NULL)
4075 SYSCALL_TRACK( pre_mem_write, tid, "nanosleep(rem)", arg2,
4076 sizeof(struct timespec) );
jsgf855d93d2003-10-13 22:26:55 +00004077}
4078
4079POST(nanosleep)
4080{
thughesbaa46e52004-07-29 17:44:23 +00004081 if (arg2 != (UInt)NULL && res == -VKI_EINTR)
jsgf855d93d2003-10-13 22:26:55 +00004082 VG_TRACK( post_mem_write, arg2, sizeof(struct timespec) );
4083}
4084
4085PRE(_newselect)
4086{
4087 /* int select(int n,
4088 fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
4089 struct timeval *timeout);
4090 */
4091 MAYBE_PRINTF("newselect ( %d, %p, %p, %p, %p )\n",
4092 arg1,arg2,arg3,arg4,arg5);
4093 if (arg2 != 0)
4094 SYSCALL_TRACK( pre_mem_read, tid, "newselect(readfds)",
4095 arg2, arg1/8 /* __FD_SETSIZE/8 */ );
4096 if (arg3 != 0)
4097 SYSCALL_TRACK( pre_mem_read, tid, "newselect(writefds)",
4098 arg3, arg1/8 /* __FD_SETSIZE/8 */ );
4099 if (arg4 != 0)
4100 SYSCALL_TRACK( pre_mem_read, tid, "newselect(exceptfds)",
4101 arg4, arg1/8 /* __FD_SETSIZE/8 */ );
4102 if (arg5 != 0)
4103 SYSCALL_TRACK( pre_mem_read, tid, "newselect(timeout)", arg5,
4104 sizeof(struct timeval) );
4105}
4106
4107PRE(open)
4108{
4109 /* int open(const char *pathname, int flags); */
4110 MAYBE_PRINTF("open ( %p(%s), %d ) --> ",arg1,arg1,arg2);
4111 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "open(pathname)", arg1 );
4112}
4113
4114POST(open)
4115{
thughesad1c9562004-06-26 11:27:52 +00004116 if (!fd_allowed(res, "open", tid, True)) {
jsgf855d93d2003-10-13 22:26:55 +00004117 VG_(close)(res);
4118 res = -VKI_EMFILE;
rjwalshf5f536f2003-11-17 17:45:00 +00004119 } else {
nethercote493dd182004-02-24 23:57:47 +00004120 if (VG_(clo_track_fds))
fitzhardingea7728472003-12-16 01:48:38 +00004121 record_fd_open(tid, res, VG_(arena_strdup)(VG_AR_CORE, (Char*)arg1));
jsgf855d93d2003-10-13 22:26:55 +00004122 }
4123 MAYBE_PRINTF("%d\n",res);
4124}
4125
4126PRE(read)
4127{
4128 /* size_t read(int fd, void *buf, size_t count); */
4129 MAYBE_PRINTF("read ( %d, %p, %d )\n", arg1, arg2, arg3);
4130
thughesad1c9562004-06-26 11:27:52 +00004131 if (!fd_allowed(arg1, "read", tid, False))
jsgf855d93d2003-10-13 22:26:55 +00004132 res = -VKI_EBADF;
4133}
4134
4135POST(read)
4136{
4137 if (res > 0)
4138 VG_TRACK(post_mem_write, arg2, res);
4139}
4140
4141PRE(write)
4142{
4143 /* size_t write(int fd, const void *buf, size_t count); */
4144 MAYBE_PRINTF("write ( %d, %p, %d )\n", arg1, arg2, arg3);
thughesad1c9562004-06-26 11:27:52 +00004145 if (!fd_allowed(arg1, "write", tid, False))
jsgf855d93d2003-10-13 22:26:55 +00004146 res = -VKI_EBADF;
4147 else
4148 SYSCALL_TRACK( pre_mem_read, tid, "write(buf)", arg2, arg3 );
4149}
4150
4151PRE(creat)
4152{
4153 /* int creat(const char *pathname, mode_t mode); */
4154 MAYBE_PRINTF("creat ( %p(%s), %d ) --> ",arg1,arg1,arg2);
4155 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "creat(pathname)", arg1 );
4156}
4157
4158POST(creat)
4159{
thughesad1c9562004-06-26 11:27:52 +00004160 if (!fd_allowed(res, "creat", tid, True)) {
jsgf855d93d2003-10-13 22:26:55 +00004161 VG_(close)(res);
4162 res = -VKI_EMFILE;
rjwalshf5f536f2003-11-17 17:45:00 +00004163 } else {
nethercote493dd182004-02-24 23:57:47 +00004164 if (VG_(clo_track_fds))
fitzhardingea7728472003-12-16 01:48:38 +00004165 record_fd_open(tid, res, VG_(arena_strdup)(VG_AR_CORE, (Char*)arg1));
jsgf855d93d2003-10-13 22:26:55 +00004166 }
4167 MAYBE_PRINTF("%d\n",res);
4168}
4169
4170PRE(pipe)
4171{
4172 /* int pipe(int filedes[2]); */
4173 MAYBE_PRINTF("pipe ( %p ) ...\n", arg1);
4174 SYSCALL_TRACK( pre_mem_write, tid, "pipe(filedes)",
4175 arg1, 2*sizeof(int) );
4176}
4177
4178POST(pipe)
4179{
4180 Int *p = (Int *)arg1;
4181
thughesad1c9562004-06-26 11:27:52 +00004182 if (!fd_allowed(p[0], "pipe", tid, True) ||
4183 !fd_allowed(p[1], "pipe", tid, True)) {
jsgf855d93d2003-10-13 22:26:55 +00004184 VG_(close)(p[0]);
4185 VG_(close)(p[1]);
4186 res = -VKI_EMFILE;
rjwalshf5f536f2003-11-17 17:45:00 +00004187 } else {
jsgf855d93d2003-10-13 22:26:55 +00004188 VG_TRACK( post_mem_write, arg1, 2*sizeof(int) );
nethercote493dd182004-02-24 23:57:47 +00004189 if (VG_(clo_track_fds)) {
rjwalshf5f536f2003-11-17 17:45:00 +00004190 record_fd_open(tid, p[0], NULL);
4191 record_fd_open(tid, p[1], NULL);
4192 }
4193 }
jsgf855d93d2003-10-13 22:26:55 +00004194
4195 MAYBE_PRINTF("SYSCALL[%d] pipe --> %d (rd %d, wr %d)\n",
4196 VG_(getpid)(), res,
4197 ((UInt*)arg1)[0], ((UInt*)arg1)[1] );
4198}
4199
4200PRE(poll)
4201{
4202 /* struct pollfd {
4203 int fd; -- file descriptor
4204 short events; -- requested events
4205 short revents; -- returned events
4206 };
4207 int poll(struct pollfd *ufds, unsigned int nfds,
4208 int timeout)
4209 */
4210 MAYBE_PRINTF("poll ( %p, %d, %d )\n",arg1,arg2,arg3);
4211 /* In fact some parts of this struct should be readable too.
4212 This should be fixed properly. */
4213 SYSCALL_TRACK( pre_mem_write, tid, "poll(ufds)",
4214 arg1, arg2 * sizeof(struct pollfd) );
4215}
4216
4217POST(poll)
4218{
4219 if (res > 0) {
4220 UInt i;
4221 struct pollfd * arr = (struct pollfd *)arg1;
4222 for (i = 0; i < arg2; i++)
4223 VG_TRACK( post_mem_write, (Addr)(&arr[i].revents),
4224 sizeof(Short) );
4225 }
4226}
4227
nethercote9af69b32004-02-10 23:44:15 +00004228PRE(epoll_create)
4229{
4230 /* int epoll_create(int size) */
4231 MAYBE_PRINTF("epoll_create ( %d )\n", arg1);
4232}
4233
4234POST(epoll_create)
4235{
thughesad1c9562004-06-26 11:27:52 +00004236 if (!fd_allowed(res, "open", tid, True)) {
nethercote9af69b32004-02-10 23:44:15 +00004237 VG_(close)(res);
4238 res = -VKI_EMFILE;
4239 } else {
4240 if (VG_(clo_track_fds))
4241 record_fd_open (tid, res, NULL);
4242 }
4243}
4244
4245PRE(epoll_ctl)
4246{
4247 /* int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) */
4248 static const char* epoll_ctl_s[3] = {
4249 "EPOLL_CTL_ADD",
4250 "EPOLL_CTL_DEL",
4251 "EPOLL_CTL_MOD"
4252 };
4253 MAYBE_PRINTF("epoll_ctl ( %d, %s, %d, %p )\n",
4254 arg1, ( arg2<3 ? epoll_ctl_s[arg2] : "?" ), arg3, arg4);
4255 SYSCALL_TRACK( pre_mem_read, tid, "epoll_ctl(event)",
4256 arg4, sizeof(struct vki_epoll_event) );
4257}
4258
4259PRE(epoll_wait)
4260{
4261 /* int epoll_wait(int epfd, struct epoll_event * events,
4262 int maxevents, int timeout) */
4263 MAYBE_PRINTF("epoll_wait ( %d, %p, %d, %d )\n", arg1, arg2, arg3, arg4);
4264 SYSCALL_TRACK( pre_mem_write, tid, "epoll_wait(events)",
4265 arg2, sizeof(struct vki_epoll_event)*arg3);
4266}
4267
4268POST(epoll_wait)
4269{
4270 if (res > 0)
4271 VG_TRACK( post_mem_write, arg2, sizeof(struct vki_epoll_event)*res ) ;
4272}
4273
jsgf855d93d2003-10-13 22:26:55 +00004274PRE(readlink)
4275{
4276 /* int readlink(const char *path, char *buf, size_t bufsiz); */
4277 MAYBE_PRINTF("readlink ( %p, %p, %d )\n", arg1,arg2,arg3);
4278 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "readlink(path)", arg1 );
4279 SYSCALL_TRACK( pre_mem_write, tid, "readlink(buf)", arg2,arg3 );
4280}
4281
4282POST(readlink)
4283{
4284 VG_TRACK( post_mem_write, arg2, res );
4285}
4286
4287PRE(readv)
4288{
4289 /* int readv(int fd, const struct iovec * vector, size_t count); */
4290 Int i;
4291 struct iovec * vec;
4292 MAYBE_PRINTF("readv ( %d, %p, %d )\n",arg1,arg2,arg3);
thughesad1c9562004-06-26 11:27:52 +00004293 if (!fd_allowed(arg1, "readv", tid, False)) {
jsgf855d93d2003-10-13 22:26:55 +00004294 res = -VKI_EBADF;
4295 } else {
4296 SYSCALL_TRACK( pre_mem_read, tid, "readv(vector)",
4297 arg2, arg3 * sizeof(struct iovec) );
4298 /* ToDo: don't do any of the following if the vector is invalid */
4299 vec = (struct iovec *)arg2;
4300 for (i = 0; i < (Int)arg3; i++)
4301 SYSCALL_TRACK( pre_mem_write, tid, "readv(vector[...])",
4302 (UInt)vec[i].iov_base,vec[i].iov_len );
4303 }
4304}
4305
4306POST(readv)
4307{
4308 if (res > 0) {
4309 Int i;
4310 struct iovec * vec = (struct iovec *)arg2;
4311 Int remains = res;
4312
4313 /* res holds the number of bytes read. */
4314 for (i = 0; i < (Int)arg3; i++) {
4315 Int nReadThisBuf = vec[i].iov_len;
4316 if (nReadThisBuf > remains) nReadThisBuf = remains;
4317 VG_TRACK( post_mem_write, (UInt)vec[i].iov_base, nReadThisBuf );
4318 remains -= nReadThisBuf;
4319 if (remains < 0) VG_(core_panic)("readv: remains < 0");
4320 }
4321 }
4322}
4323
4324PRE(rename)
4325{
4326 /* int rename(const char *oldpath, const char *newpath); */
4327 MAYBE_PRINTF("rename ( %p, %p )\n", arg1, arg2 );
4328 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "rename(oldpath)", arg1 );
4329 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "rename(newpath)", arg2 );
4330}
4331
4332PRE(rmdir)
4333{
4334 /* int rmdir(const char *pathname); */
4335 MAYBE_PRINTF("rmdir ( %p )\n", arg1);
4336 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "rmdir(pathname)", arg1 );
4337}
4338
4339PRE(sched_setparam)
4340{
4341 /* int sched_setparam(pid_t pid, const struct sched_param *p); */
4342 MAYBE_PRINTF("sched_setparam ( %d, %p )\n", arg1, arg2 );
4343 SYSCALL_TRACK( pre_mem_read, tid, "sched_setparam(ptr)",
4344 arg2, sizeof(struct sched_param) );
4345}
4346
4347POST(sched_setparam)
4348{
4349 VG_TRACK( post_mem_write, arg2, sizeof(struct sched_param) );
4350}
4351
4352PRE(sched_getparam)
4353{
4354 /* int sched_getparam(pid_t pid, struct sched_param *p); */
4355 MAYBE_PRINTF("sched_getparam ( %d, %p )\n", arg1, arg2 );
4356 SYSCALL_TRACK( pre_mem_write, tid, "sched_getparam(ptr)",
4357 arg2, sizeof(struct sched_param) );
4358}
4359
4360POST(sched_getparam)
4361{
4362 VG_TRACK( post_mem_write, arg2, sizeof(struct sched_param) );
4363}
4364
4365PRE(sched_yield)
4366{
4367 /* int sched_yield(void); */
4368 MAYBE_PRINTF("sched_yield ()\n" );
4369}
4370
4371PRE(select)
4372{
4373 /* struct sel_arg_struct {
4374 unsigned long n;
4375 fd_set *inp, *outp, *exp;
4376 struct timeval *tvp;
4377 };
4378 int old_select(struct sel_arg_struct *arg);
4379 */
4380 SYSCALL_TRACK( pre_mem_read, tid, "select(args)", arg1, 5*sizeof(UInt) );
4381
4382 {
4383 UInt* arg_struct = (UInt*)arg1;
4384 UInt a1, a2, a3, a4, a5;
4385
4386 a1 = arg_struct[0];
4387 a2 = arg_struct[1];
4388 a3 = arg_struct[2];
4389 a4 = arg_struct[3];
4390 a5 = arg_struct[4];
4391
4392 MAYBE_PRINTF("select ( %d, %p, %p, %p, %p )\n",
4393 a1,a2,a3,a4,a5);
4394 if (a2 != (Addr)NULL)
4395 SYSCALL_TRACK( pre_mem_read, tid, "select(readfds)", a2,
4396 a1/8 /* __FD_SETSIZE/8 */ );
4397 if (a3 != (Addr)NULL)
4398 SYSCALL_TRACK( pre_mem_read, tid, "select(writefds)", a3,
nethercotea4c33c62004-02-15 15:10:25 +00004399 a1/8 /* __FD_SETSIZE/8 */ );
jsgf855d93d2003-10-13 22:26:55 +00004400 if (a4 != (Addr)NULL)
4401 SYSCALL_TRACK( pre_mem_read, tid, "select(exceptfds)", a4,
4402 a1/8 /* __FD_SETSIZE/8 */ );
4403 if (a5 != (Addr)NULL)
4404 SYSCALL_TRACK( pre_mem_read, tid, "select(timeout)", a5,
4405 sizeof(struct timeval) );
4406 }
4407}
4408
4409PRE(setitimer)
4410{
4411 /* setitimer(int which, const struct itimerval *value,
4412 struct itimerval *ovalue); */
4413 MAYBE_PRINTF("setitimer ( %d, %p, %p )\n", arg1,arg2,arg3);
4414 if (arg2 != (Addr)NULL)
4415 SYSCALL_TRACK( pre_mem_read,tid, "setitimer(value)",
4416 arg2, sizeof(struct itimerval) );
4417 if (arg3 != (Addr)NULL)
4418 SYSCALL_TRACK( pre_mem_write,tid, "setitimer(ovalue)",
4419 arg3, sizeof(struct itimerval));
4420}
4421
4422POST(setitimer)
4423{
4424 if (arg3 != (Addr)NULL) {
4425 VG_TRACK( post_mem_write,arg3, sizeof(struct itimerval));
4426 }
4427}
4428
4429PRE(setfsgid32)
4430{
4431 /* int setfsgid(uid_t fsgid); */
4432 MAYBE_PRINTF("setfsgid ( %d )\n", arg1);
4433}
4434
4435PRE(setgid)
4436{
4437 /* int setgid(gid_t gid); */
4438 MAYBE_PRINTF("setgid ( %d )\n", arg1);
4439}
4440
4441PREALIAS(setgid32, setgid);
4442
4443PRE(setsid)
4444{
4445 /* pid_t setsid(void); */
4446 MAYBE_PRINTF("setsid ()\n");
4447}
4448
4449PRE(setgroups)
4450{
4451 /* int setgroups(size_t size, const gid_t *list); */
4452 MAYBE_PRINTF("setgroups ( %d, %p )\n", arg1, arg2);
4453 if (arg1 > 0)
4454 SYSCALL_TRACK( pre_mem_read, tid, "setgroups(list)", arg2,
4455 arg1 * sizeof(gid_t) );
4456}
4457
4458PREALIAS(setgroups32, setgroups);
4459
4460PRE(setpgid)
4461{
4462 /* int setpgid(pid_t pid, pid_t pgid); */
4463 MAYBE_PRINTF("setpgid ( %d, %d )\n", arg1, arg2);
4464}
4465
4466POST(setpgid)
4467{
4468 VG_(main_pgrp) = VG_(getpgrp)();
4469}
4470
4471PRE(setregid32)
4472{
4473 /* int setregid(gid_t rgid, gid_t egid); */
4474 MAYBE_PRINTF("setregid32(?) ( %d, %d )\n", arg1, arg2);
4475}
4476
4477PRE(setresuid32)
4478{
4479 /* int setresuid(uid_t ruid, uid_t euid, uid_t suid); */
4480 MAYBE_PRINTF("setresuid32(?) ( %d, %d, %d )\n", arg1, arg2, arg3);
4481}
4482
4483PRE(setreuid)
4484{
4485 /* int setreuid(uid_t ruid, uid_t euid); */
4486 MAYBE_PRINTF("setreuid ( 0x%x, 0x%x )\n", arg1, arg2);
4487}
4488
4489PREALIAS(setreuid32, setreuid);
4490
4491PRE(setrlimit)
4492{
4493 /* int setrlimit (int resource, const struct rlimit *rlim); */
4494 MAYBE_PRINTF("setrlimit ( %d, %p )\n", arg1,arg2);
4495 SYSCALL_TRACK( pre_mem_read, tid, "setrlimit(rlim)",
fitzhardingeb50068f2004-02-24 23:42:55 +00004496 arg2, sizeof(struct vki_rlimit) );
4497
thughesad1c9562004-06-26 11:27:52 +00004498 if (arg1 == VKI_RLIMIT_NOFILE) {
4499 if (((vki_rlimit *)arg2)->rlim_cur > VG_(fd_hard_limit) ||
4500 ((vki_rlimit *)arg2)->rlim_max != VG_(fd_hard_limit)) {
4501 res = -VKI_EPERM;
4502 }
4503 else {
4504 VG_(fd_soft_limit) = ((vki_rlimit *)arg2)->rlim_cur;
4505 res = 0;
4506 }
4507 }
4508 else if (arg1 == VKI_RLIMIT_DATA) {
fitzhardingeb50068f2004-02-24 23:42:55 +00004509 VG_(client_rlimit_data) = *(vki_rlimit *)arg2;
4510 res = 0;
4511 }
jsgf855d93d2003-10-13 22:26:55 +00004512}
4513
4514PRE(setuid)
4515{
4516 /* int setuid(uid_t uid); */
4517 MAYBE_PRINTF("setuid ( %d )\n", arg1);
4518}
4519
4520PREALIAS(setuid32, setuid);
4521
4522PRE(socketcall)
4523{
4524 /* int socketcall(int call, unsigned long *args); */
4525 MAYBE_PRINTF("socketcall ( %d, %p )\n",arg1,arg2);
4526 switch (arg1 /* request */) {
4527
4528 case SYS_SOCKETPAIR:
4529 /* int socketpair(int d, int type, int protocol, int sv[2]); */
4530 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.socketpair(args)",
4531 arg2, 4*sizeof(Addr) );
4532 SYSCALL_TRACK( pre_mem_write, tid, "socketcall.socketpair(sv)",
4533 ((UInt*)arg2)[3], 2*sizeof(int) );
4534 break;
4535
4536 case SYS_SOCKET:
4537 /* int socket(int domain, int type, int protocol); */
4538 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.socket(args)",
4539 arg2, 3*sizeof(Addr) );
4540 break;
4541
4542 case SYS_BIND:
4543 /* int bind(int sockfd, struct sockaddr *my_addr,
4544 int addrlen); */
4545 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.bind(args)",
4546 arg2, 3*sizeof(Addr) );
4547 pre_mem_read_sockaddr( tid, "socketcall.bind(my_addr.%s)",
4548 (struct sockaddr *) (((UInt*)arg2)[1]), ((UInt*)arg2)[2]);
4549 break;
4550
4551 case SYS_LISTEN:
4552 /* int listen(int s, int backlog); */
4553 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.listen(args)",
4554 arg2, 2*sizeof(Addr) );
4555 break;
4556
4557 case SYS_ACCEPT: {
4558 /* int accept(int s, struct sockaddr *addr, int *addrlen); */
4559 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.accept(args)",
4560 arg2, 3*sizeof(Addr) );
4561 {
4562 Addr addr_p = ((UInt*)arg2)[1];
4563 Addr addrlen_p = ((UInt*)arg2)[2];
4564 if (addr_p != (Addr)NULL)
4565 buf_and_len_pre_check ( tid, addr_p, addrlen_p,
4566 "socketcall.accept(addr)",
4567 "socketcall.accept(addrlen_in)" );
4568 }
4569 break;
4570 }
4571
4572 case SYS_SENDTO:
4573 /* int sendto(int s, const void *msg, int len,
4574 unsigned int flags,
4575 const struct sockaddr *to, int tolen); */
4576 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.sendto(args)", arg2,
4577 6*sizeof(Addr) );
4578 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.sendto(msg)",
4579 ((UInt*)arg2)[1], /* msg */
4580 ((UInt*)arg2)[2] /* len */ );
4581 pre_mem_read_sockaddr( tid, "socketcall.sendto(to.%s)",
4582 (struct sockaddr *) (((UInt*)arg2)[4]), ((UInt*)arg2)[5]);
4583 break;
4584
4585 case SYS_SEND:
4586 /* int send(int s, const void *msg, size_t len, int flags); */
4587 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.send(args)", arg2,
4588 4*sizeof(Addr) );
4589 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.send(msg)",
4590 ((UInt*)arg2)[1], /* msg */
4591 ((UInt*)arg2)[2] /* len */ );
4592 break;
4593
4594 case SYS_RECVFROM:
4595 /* int recvfrom(int s, void *buf, int len, unsigned int flags,
4596 struct sockaddr *from, int *fromlen); */
4597 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.recvfrom(args)",
4598 arg2, 6*sizeof(Addr) );
4599 {
4600 Addr buf_p = ((UInt*)arg2)[1];
4601 Int len = ((UInt*)arg2)[2];
4602 Addr from_p = ((UInt*)arg2)[4];
4603 Addr fromlen_p = ((UInt*)arg2)[5];
4604
4605 SYSCALL_TRACK( pre_mem_write, tid, "socketcall.recvfrom(buf)",
4606 buf_p, len );
4607 if (from_p != (Addr)NULL)
4608 buf_and_len_pre_check ( tid, from_p, fromlen_p,
4609 "socketcall.recvfrom(from)",
4610 "socketcall.recvfrom(fromlen_in)" );
4611 }
4612 break;
4613
4614 case SYS_RECV:
4615 /* int recv(int s, void *buf, int len, unsigned int flags); */
4616 /* man 2 recv says:
4617 The recv call is normally used only on a connected socket
4618 (see connect(2)) and is identical to recvfrom with a NULL
4619 from parameter.
4620 */
4621 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.recv(args)",
4622 arg2, 4*sizeof(Addr) );
4623 SYSCALL_TRACK( pre_mem_write, tid, "socketcall.recv(buf)",
4624 ((UInt*)arg2)[1], /* buf */
4625 ((UInt*)arg2)[2] /* len */ );
4626 break;
4627
4628 case SYS_CONNECT:
4629 /* int connect(int sockfd,
4630 struct sockaddr *serv_addr, int addrlen ); */
4631 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.connect(args)",
4632 arg2, 3*sizeof(Addr) );
4633 SYSCALL_TRACK( pre_mem_read, tid,
4634 "socketcall.connect(serv_addr.sa_family)",
4635 ((UInt*)arg2)[1], /* serv_addr */
4636 sizeof (sa_family_t));
4637 pre_mem_read_sockaddr( tid,
4638 "socketcall.connect(serv_addr.%s)",
4639 (struct sockaddr *) (((UInt*)arg2)[1]), ((UInt*)arg2)[2]);
4640 break;
4641
4642 case SYS_SETSOCKOPT:
4643 /* int setsockopt(int s, int level, int optname,
4644 const void *optval, int optlen); */
4645 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.setsockopt(args)",
4646 arg2, 5*sizeof(Addr) );
4647 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.setsockopt(optval)",
4648 ((UInt*)arg2)[3], /* optval */
4649 ((UInt*)arg2)[4] /* optlen */ );
4650 break;
4651
4652 case SYS_GETSOCKOPT:
4653 /* int setsockopt(int s, int level, int optname,
4654 void *optval, socklen_t *optlen); */
4655 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.getsockopt(args)",
4656 arg2, 5*sizeof(Addr) );
4657 {
4658 Addr optval_p = ((UInt*)arg2)[3];
4659 Addr optlen_p = ((UInt*)arg2)[4];
4660 /* vg_assert(sizeof(socklen_t) == sizeof(UInt)); */
4661 if (optval_p != (Addr)NULL)
4662 buf_and_len_pre_check ( tid, optval_p, optlen_p,
4663 "socketcall.getsockopt(optval)",
4664 "socketcall.getsockopt(optlen)" );
4665 }
4666 break;
4667
4668 case SYS_GETSOCKNAME:
4669 /* int getsockname(int s, struct sockaddr* name, int* namelen) */
4670 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.getsockname(args)",
4671 arg2, 3*sizeof(Addr) );
4672 {
4673 Addr name_p = ((UInt*)arg2)[1];
4674 Addr namelen_p = ((UInt*)arg2)[2];
4675
4676 /* Nb: name_p cannot be NULL */
4677 buf_and_len_pre_check ( tid, name_p, namelen_p,
4678 "socketcall.getsockname(name)",
4679 "socketcall.getsockname(namelen_in)" );
4680 }
4681 break;
4682
4683 case SYS_GETPEERNAME:
4684 /* int getpeername(int s, struct sockaddr* name, int* namelen) */
4685 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.getpeername(args)",
4686 arg2, 3*sizeof(Addr) );
4687 {
4688 Addr name_p = ((UInt*)arg2)[1];
4689 Addr namelen_p = ((UInt*)arg2)[2];
4690
4691 /* Nb: name_p cannot be NULL */
4692 buf_and_len_pre_check ( tid, name_p, namelen_p,
4693 "socketcall.getpeername(name)",
4694 "socketcall.getpeername(namelen_in)" );
4695 }
4696 break;
4697
4698 case SYS_SHUTDOWN:
4699 /* int shutdown(int s, int how); */
4700 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.shutdown(args)",
4701 arg2, 2*sizeof(Addr) );
4702 break;
4703
4704 case SYS_SENDMSG: {
4705 /* int sendmsg(int s, const struct msghdr *msg, int flags); */
4706
4707 /* this causes warnings, and I don't get why. glibc bug?
4708 * (after all it's glibc providing the arguments array)
4709 SYSCALL_TRACK( pre_mem_read, "socketcall.sendmsg(args)",
4710 arg2, 3*sizeof(Addr) );
4711 */
4712
4713 struct msghdr *msg = (struct msghdr *)((UInt *)arg2)[ 1 ];
4714 msghdr_foreachfield ( tid, msg, pre_mem_read_sendmsg );
4715
4716 break;
4717 }
4718
4719 case SYS_RECVMSG: {
4720 /* int recvmsg(int s, struct msghdr *msg, int flags); */
4721
4722 /* this causes warnings, and I don't get why. glibc bug?
4723 * (after all it's glibc providing the arguments array)
4724 SYSCALL_TRACK( pre_mem_read, "socketcall.recvmsg(args)",
4725 arg2, 3*sizeof(Addr) );
4726 */
4727
4728 struct msghdr *msg = (struct msghdr *)((UInt *)arg2)[ 1 ];
4729 msghdr_foreachfield ( tid, msg, pre_mem_write_recvmsg );
4730
4731 break;
4732 }
4733
4734 default:
jsgf17059e02003-10-19 16:46:06 +00004735 VG_(message)(Vg_DebugMsg,"Warning: unhandled socketcall 0x%x",arg1);
4736 res = -VKI_EINVAL;
4737 break;
jsgf855d93d2003-10-13 22:26:55 +00004738 }
4739}
4740
4741POST(socketcall)
4742{
4743 /* int socketcall(int call, unsigned long *args); */
4744 MAYBE_PRINTF("socketcall ( %d, %p )\n",arg1,arg2);
4745
4746 switch (arg1 /* request */) {
4747
nethercote493dd182004-02-24 23:57:47 +00004748 case SYS_SOCKETPAIR: {
4749 Int fd1 = ((UInt*)((UInt*)arg2)[3])[0];
4750 Int fd2 = ((UInt*)((UInt*)arg2)[3])[1];
jsgf855d93d2003-10-13 22:26:55 +00004751 VG_TRACK( post_mem_write, ((UInt*)arg2)[3], 2*sizeof(int) );
thughesad1c9562004-06-26 11:27:52 +00004752 if (!fd_allowed(fd1, "socketcall.socketpair", tid, True) ||
4753 !fd_allowed(fd2, "socketcall.socketpair", tid, True)) {
nethercote493dd182004-02-24 23:57:47 +00004754 VG_(close)(fd1);
4755 VG_(close)(fd2);
4756 res = -VKI_EMFILE;
4757 } else {
4758 VG_TRACK( post_mem_write, ((UInt*)arg2)[3], 2*sizeof(int) );
4759 if (VG_(clo_track_fds)) {
4760 record_fd_open(tid, fd1, NULL);
4761 record_fd_open(tid, fd2, NULL);
4762 }
rjwalshf5f536f2003-11-17 17:45:00 +00004763 }
jsgf855d93d2003-10-13 22:26:55 +00004764 break;
nethercote493dd182004-02-24 23:57:47 +00004765 }
jsgf855d93d2003-10-13 22:26:55 +00004766
4767 case SYS_SOCKET:
thughesad1c9562004-06-26 11:27:52 +00004768 if (!fd_allowed(res, "socket", tid, True)) {
jsgf855d93d2003-10-13 22:26:55 +00004769 VG_(close)(res);
4770 res = -VKI_EMFILE;
rjwalshf5f536f2003-11-17 17:45:00 +00004771 } else {
nethercote493dd182004-02-24 23:57:47 +00004772 if (VG_(clo_track_fds))
rjwalshf5f536f2003-11-17 17:45:00 +00004773 record_fd_open(tid, res, NULL);
jsgf855d93d2003-10-13 22:26:55 +00004774 }
4775 break;
4776
4777 case SYS_BIND:
4778 /* int bind(int sockfd, struct sockaddr *my_addr,
4779 int addrlen); */
4780 break;
4781
4782 case SYS_LISTEN:
4783 /* int listen(int s, int backlog); */
4784 break;
4785
4786 case SYS_ACCEPT: {
4787 /* int accept(int s, struct sockaddr *addr, int *addrlen); */
thughesad1c9562004-06-26 11:27:52 +00004788 if (!fd_allowed(res, "accept", tid, True)) {
jsgf855d93d2003-10-13 22:26:55 +00004789 VG_(close)(res);
4790 res = -VKI_EMFILE;
4791 } else {
4792 Addr addr_p = ((UInt*)arg2)[1];
4793 Addr addrlen_p = ((UInt*)arg2)[2];
4794
4795 if (addr_p != (Addr)NULL)
4796 buf_and_len_post_check ( tid, res, addr_p, addrlen_p,
4797 "socketcall.accept(addrlen_out)" );
nethercote493dd182004-02-24 23:57:47 +00004798 if (VG_(clo_track_fds))
rjwalshf5f536f2003-11-17 17:45:00 +00004799 record_fd_open(tid, res, NULL);
jsgf855d93d2003-10-13 22:26:55 +00004800 }
4801 break;
4802 }
4803
4804 case SYS_SENDTO:
4805 break;
4806
4807 case SYS_SEND:
4808 break;
4809
4810 case SYS_RECVFROM:
4811 {
4812 Addr buf_p = ((UInt*)arg2)[1];
4813 Int len = ((UInt*)arg2)[2];
4814 Addr from_p = ((UInt*)arg2)[4];
4815 Addr fromlen_p = ((UInt*)arg2)[5];
4816
4817 if (from_p != (Addr)NULL)
4818 buf_and_len_post_check ( tid, res, from_p, fromlen_p,
4819 "socketcall.recvfrom(fromlen_out)" );
4820 VG_TRACK( post_mem_write, buf_p, len );
4821 }
4822 break;
4823
4824 case SYS_RECV:
4825 if (res >= 0
4826 && ((UInt*)arg2)[1] != (UInt)NULL) {
4827 VG_TRACK( post_mem_write, ((UInt*)arg2)[1], /* buf */
4828 ((UInt*)arg2)[2] /* len */ );
4829 }
4830 break;
4831
4832 case SYS_CONNECT:
4833 break;
4834
4835 case SYS_SETSOCKOPT:
4836 break;
4837
4838 case SYS_GETSOCKOPT:
4839 {
4840 Addr optval_p = ((UInt*)arg2)[3];
4841 Addr optlen_p = ((UInt*)arg2)[4];
4842
4843 if (optval_p != (Addr)NULL)
4844 buf_and_len_post_check ( tid, res, optval_p, optlen_p,
4845 "socketcall.getsockopt(optlen_out)" );
4846 }
4847 break;
4848
4849 case SYS_GETSOCKNAME:
4850 {
4851 Addr name_p = ((UInt*)arg2)[1];
4852 Addr namelen_p = ((UInt*)arg2)[2];
4853
4854 buf_and_len_post_check ( tid, res, name_p, namelen_p,
4855 "socketcall.getsockname(namelen_out)" );
4856 }
4857 break;
4858
4859 case SYS_GETPEERNAME:
4860 {
4861 Addr name_p = ((UInt*)arg2)[1];
4862 Addr namelen_p = ((UInt*)arg2)[2];
4863
4864 buf_and_len_post_check ( tid, res, name_p, namelen_p,
4865 "socketcall.getpeername(namelen_out)" );
4866 }
4867 break;
4868
4869 case SYS_SHUTDOWN:
4870 break;
4871
4872 case SYS_SENDMSG:
4873 break;
4874
4875 case SYS_RECVMSG:
4876 {
4877 struct msghdr *msg = (struct msghdr *)((UInt *)arg2)[ 1 ];
4878
4879 msghdr_foreachfield( tid, msg, post_mem_write_recvmsg );
rjwalshf5f536f2003-11-17 17:45:00 +00004880 check_cmsg_for_fds( tid, msg );
jsgf855d93d2003-10-13 22:26:55 +00004881
4882 break;
4883 }
4884
4885 default:
4886 VG_(message)(Vg_DebugMsg,"FATAL: unhandled socketcall 0x%x",arg1);
4887 VG_(core_panic)("... bye!\n");
4888 break; /*NOTREACHED*/
4889 }
4890}
4891
4892PRE(stat)
4893{
4894 /* int stat(const char *file_name, struct stat *buf); */
4895 MAYBE_PRINTF("stat ( %p, %p )\n",arg1,arg2);
4896 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "stat(file_name)", arg1 );
4897 SYSCALL_TRACK( pre_mem_write, tid, "stat(buf)",
4898 arg2, sizeof(struct stat) );
4899}
4900
4901POST(stat)
4902{
4903 VG_TRACK( post_mem_write, arg2, sizeof(struct stat) );
4904}
4905
4906PRE(statfs)
4907{
4908 /* int statfs(const char *path, struct statfs *buf); */
4909 MAYBE_PRINTF("statfs ( %p, %p )\n",arg1,arg2);
4910 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "statfs(path)", arg1 );
muellerd3502b62003-11-19 00:43:57 +00004911 SYSCALL_TRACK( pre_mem_write, tid, "statfs(buf)",
thughes66d80092004-06-19 12:41:05 +00004912 arg2, sizeof(struct vki_statfs) );
muellerd3502b62003-11-19 00:43:57 +00004913}
4914
mueller44cbaeb2003-11-19 08:56:44 +00004915POST(statfs)
4916{
thughes66d80092004-06-19 12:41:05 +00004917 VG_TRACK( post_mem_write, arg2, sizeof(struct vki_statfs) );
mueller44cbaeb2003-11-19 08:56:44 +00004918}
4919
muellerd3502b62003-11-19 00:43:57 +00004920PRE(statfs64)
4921{
4922 /* int statfs64(const char *path, struct statfs *buf); */
4923 MAYBE_PRINTF("statfs64 ( %p, %p )\n",arg1,arg2);
4924 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "statfs64(path)", arg1 );
4925 SYSCALL_TRACK( pre_mem_write, tid, "statfs64(buf)",
thughes66d80092004-06-19 12:41:05 +00004926 arg2, sizeof(struct vki_statfs64) );
jsgf855d93d2003-10-13 22:26:55 +00004927}
4928
muellerd3502b62003-11-19 00:43:57 +00004929POST(statfs64)
4930{
thughes66d80092004-06-19 12:41:05 +00004931 VG_TRACK( post_mem_write, arg2, sizeof(struct vki_statfs64) );
muellerd3502b62003-11-19 00:43:57 +00004932}
4933
jsgf855d93d2003-10-13 22:26:55 +00004934PRE(symlink)
4935{
4936 /* int symlink(const char *oldpath, const char *newpath); */
4937 MAYBE_PRINTF("symlink ( %p, %p )\n",arg1,arg2);
4938 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "symlink(oldpath)", arg1 );
4939 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "symlink(newpath)", arg2 );
4940}
4941
4942PRE(stat64)
4943{
4944 /* int stat64(const char *file_name, struct stat64 *buf); */
4945 MAYBE_PRINTF("stat64 ( %p, %p )\n",arg1,arg2);
4946 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "stat64(file_name)", arg1 );
4947 SYSCALL_TRACK( pre_mem_write, tid, "stat64(buf)",
4948 arg2, sizeof(struct stat64) );
4949}
4950
4951POST(stat64)
4952{
4953 VG_TRACK( post_mem_write, arg2, sizeof(struct stat64) );
4954}
4955
4956PRE(fstat64)
4957{
4958 /* int fstat64(int filedes, struct stat64 *buf); */
4959 MAYBE_PRINTF("fstat64 ( %d, %p )\n",arg1,arg2);
4960 SYSCALL_TRACK( pre_mem_write, tid, "fstat64(buf)",
4961 arg2, sizeof(struct stat64) );
4962}
4963
4964POST(fstat64)
4965{
4966 VG_TRACK( post_mem_write, arg2, sizeof(struct stat64) );
4967}
4968
4969PRE(sysinfo)
4970{
4971 /* int sysinfo(struct sysinfo *info); */
4972 MAYBE_PRINTF("sysinfo ( %p )\n",arg1);
4973 SYSCALL_TRACK( pre_mem_write, tid, "sysinfo(info)",
4974 arg1, sizeof(struct sysinfo) );
4975}
4976
4977POST(sysinfo)
4978{
4979 VG_TRACK( post_mem_write, arg1, sizeof(struct sysinfo) );
4980}
4981
4982PRE(time)
4983{
4984 /* time_t time(time_t *t); */
4985 MAYBE_PRINTF("time ( %p )\n",arg1);
4986 if (arg1 != (UInt)NULL) {
4987 SYSCALL_TRACK( pre_mem_write, tid, "time", arg1, sizeof(time_t) );
4988 }
4989}
4990
4991POST(time)
4992{
4993 if (arg1 != (UInt)NULL) {
4994 VG_TRACK( post_mem_write, arg1, sizeof(time_t) );
4995 }
4996}
4997
4998PRE(times)
4999{
5000 /* clock_t times(struct tms *buf); */
5001 MAYBE_PRINTF("times ( %p )\n",arg1);
5002 SYSCALL_TRACK( pre_mem_write, tid, "times(buf)",
5003 arg1, sizeof(struct tms) );
5004}
5005
5006POST(times)
5007{
5008 if (arg1 != (UInt)NULL) {
5009 VG_TRACK( post_mem_write, arg1, sizeof(struct tms) );
5010 }
5011}
5012
5013PRE(truncate)
5014{
5015 /* int truncate(const char *path, size_t length); */
fitzhardinge98abfc72003-12-16 02:05:15 +00005016 MAYBE_PRINTF("truncate ( %p \"%s\", %d )\n", arg1,arg1,arg2);
jsgf855d93d2003-10-13 22:26:55 +00005017 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "truncate(path)", arg1 );
5018}
5019
5020PRE(umask)
5021{
5022 /* mode_t umask(mode_t mask); */
5023 MAYBE_PRINTF("umask ( %d )\n", arg1);
5024}
5025
5026PRE(unlink)
5027{
5028 /* int unlink(const char *pathname) */
fitzhardinge98abfc72003-12-16 02:05:15 +00005029 MAYBE_PRINTF("unlink ( %p \"%s\" )\n",arg1, arg1);
jsgf855d93d2003-10-13 22:26:55 +00005030 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "unlink(pathname)", arg1 );
5031}
5032
5033PRE(uname)
5034{
5035 /* int uname(struct utsname *buf); */
5036 MAYBE_PRINTF("uname ( %p )\n",arg1);
5037 SYSCALL_TRACK( pre_mem_write, tid, "uname(buf)",
5038 arg1, sizeof(struct utsname) );
5039}
5040
5041POST(uname)
5042{
5043 if (arg1 != (UInt)NULL) {
5044 VG_TRACK( post_mem_write, arg1, sizeof(struct utsname) );
5045 }
5046}
5047
5048PRE(utime)
5049{
5050 /* int utime(const char *filename, struct utimbuf *buf); */
5051 MAYBE_PRINTF("utime ( %p, %p )\n", arg1,arg2);
5052 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "utime(filename)", arg1 );
5053 if (arg2 != (UInt)NULL)
5054 SYSCALL_TRACK( pre_mem_read, tid, "utime(buf)", arg2,
5055 sizeof(struct utimbuf) );
5056}
5057
5058PRE(waitpid)
5059{
5060 /* pid_t waitpid(pid_t pid, int *status, int options); */
5061
5062 MAYBE_PRINTF("waitpid ( %d, %p, %d )\n",
5063 arg1,arg2,arg3);
5064 if (arg2 != (Addr)NULL)
5065 SYSCALL_TRACK( pre_mem_write, tid, "waitpid(status)",
5066 arg2, sizeof(int) );
5067}
5068
5069POST(waitpid)
5070{
5071 if (arg2 != (Addr)NULL)
5072 VG_TRACK( post_mem_write, arg2, sizeof(int) );
5073}
5074
5075PRE(wait4)
5076{
5077 /* pid_t wait4(pid_t pid, int *status, int options,
5078 struct rusage *rusage) */
5079 MAYBE_PRINTF("wait4 ( %d, %p, %d, %p )\n",
5080 arg1,arg2,arg3,arg4);
5081 arg3 &= ~(VKI__WCLONE | VKI__WALL);
5082
5083 if (arg2 != (Addr)NULL)
5084 SYSCALL_TRACK( pre_mem_write, tid, "wait4(status)",
5085 arg2, sizeof(int) );
5086 if (arg4 != (Addr)NULL)
5087 SYSCALL_TRACK( pre_mem_write, tid, "wait4(rusage)", arg4,
5088 sizeof(struct rusage) );
5089}
5090
5091POST(wait4)
5092{
5093 if (arg2 != (Addr)NULL)
5094 VG_TRACK( post_mem_write, arg2, sizeof(int) );
5095 if (arg4 != (Addr)NULL)
5096 VG_TRACK( post_mem_write, arg4, sizeof(struct rusage) );
5097}
5098
5099PRE(writev)
5100{
5101 /* int writev(int fd, const struct iovec * vector, size_t count); */
5102 Int i;
5103 struct iovec * vec;
5104 MAYBE_PRINTF("writev ( %d, %p, %d )\n",arg1,arg2,arg3);
thughesad1c9562004-06-26 11:27:52 +00005105 if (!fd_allowed(arg1, "writev", tid, False)) {
jsgf855d93d2003-10-13 22:26:55 +00005106 res = -VKI_EBADF;
5107 } else {
5108 SYSCALL_TRACK( pre_mem_read, tid, "writev(vector)",
5109 arg2, arg3 * sizeof(struct iovec) );
5110 /* ToDo: don't do any of the following if the vector is invalid */
5111 vec = (struct iovec *)arg2;
5112 for (i = 0; i < (Int)arg3; i++)
5113 SYSCALL_TRACK( pre_mem_read, tid, "writev(vector[...])",
5114 (UInt)vec[i].iov_base,vec[i].iov_len );
5115 }
5116}
5117
5118PRE(prctl)
5119{
5120 /* int prctl(int option, unsigned long arg2, unsigned long arg3,
5121 unsigned long arg4, unsigned long arg5); */
5122 MAYBE_PRINTF( "prctl ( %d, %d, %d, %d, %d )\n", arg1, arg2, arg3,
5123 arg4, arg5 );
5124}
5125
5126PRE(adjtimex)
5127{
5128 struct timex *tx = (struct timex *)arg1;
5129 MAYBE_PRINTF("adjtimex ( %p )\n", arg1);
5130
5131 SYSCALL_TRACK(pre_mem_read, tid, "adjtimex(timex->modes)", arg1, sizeof(tx->modes));
5132
5133#define ADJX(bit,field) \
5134 if (tx->modes & bit) \
5135 SYSCALL_TRACK(pre_mem_read, tid, \
5136 "adjtimex(timex->"#field")", \
5137 (UInt)&tx->field, sizeof(tx->field))
5138 ADJX(ADJ_FREQUENCY, freq);
5139 ADJX(ADJ_MAXERROR, maxerror);
5140 ADJX(ADJ_ESTERROR, esterror);
5141 ADJX(ADJ_STATUS, status);
5142 ADJX(ADJ_TIMECONST, constant);
5143 ADJX(ADJ_TICK, tick);
5144#undef ADJX
5145
5146 SYSCALL_TRACK(pre_mem_write, tid, "adjtimex(timex)", arg1, sizeof(struct timex));
5147}
5148
5149POST(adjtimex)
5150{
5151 VG_TRACK(post_mem_write, arg1, sizeof(struct timex));
5152}
5153
muellerd3502b62003-11-19 00:43:57 +00005154PRE(clock_gettime)
5155{
5156 /* int clock_gettime(clockid_t clk_id, struct timespec *tp); */
5157 MAYBE_PRINTF("clock_gettime(%d, %p)\n" ,arg1,arg2);
5158 SYSCALL_TRACK(pre_mem_write, tid, "clock_gettime(tp)",
5159 arg2, sizeof(struct timespec));
5160}
5161
5162POST(clock_gettime)
5163{
nethercotefe082612004-07-10 18:08:13 +00005164 VG_TRACK( post_mem_write, arg2, sizeof(struct timespec) );
muellerd3502b62003-11-19 00:43:57 +00005165}
5166
5167PRE(utimes)
5168{
5169 /* int utimes(const char *filename, struct timeval *tvp); */
5170 MAYBE_PRINTF("utimes ( %p, %p )\n", arg1,arg2);
5171 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "utimes(filename)", arg1 );
5172 if (arg2 != (UInt)NULL)
5173 SYSCALL_TRACK( pre_mem_read, tid, "utimes(tvp)", arg2,
5174 sizeof(struct timeval) );
5175}
5176
fitzhardinge47735af2004-01-21 01:27:27 +00005177PRE(futex)
5178{
5179 /* int futex(void *futex, int op, int val, const struct timespec *timeout); */
5180 MAYBE_PRINTF("futex ( %p, %d, %d, %p, %p )\n", arg1,arg2,arg3,arg4,arg5);
5181 SYSCALL_TRACK( pre_mem_read, tid, "futex(futex)", arg1, sizeof(int) );
5182 if (arg2 == VKI_FUTEX_WAIT && arg4 != (UInt)NULL)
5183 SYSCALL_TRACK( pre_mem_read, tid, "futex(timeout)", arg4,
5184 sizeof(struct timespec) );
5185 if (arg2 == VKI_FUTEX_REQUEUE)
5186 SYSCALL_TRACK( pre_mem_read, tid, "futex(futex2)", arg4, sizeof(int) );
5187}
5188
5189POST(futex)
5190{
nethercotefe082612004-07-10 18:08:13 +00005191 VG_TRACK( post_mem_write, arg1, sizeof(int) );
5192 if (arg2 == VKI_FUTEX_FD) {
5193 if (!fd_allowed(res, "futex", tid, True)) {
5194 VG_(close)(res);
5195 res = -VKI_EMFILE;
5196 } else {
5197 if (VG_(clo_track_fds))
5198 record_fd_open(tid, res, VG_(arena_strdup)(VG_AR_CORE, (Char*)arg1));
nethercote493dd182004-02-24 23:57:47 +00005199 }
fitzhardinge47735af2004-01-21 01:27:27 +00005200 }
5201}
5202
nethercote2bc5a212004-04-10 00:26:10 +00005203PRE(acct)
5204{
5205 /* int acct(const char *filename); */
5206 MAYBE_PRINTF("acct ( %p )\n", arg1);
5207 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "acct(filename)", arg1 );
5208}
5209
jsgf855d93d2003-10-13 22:26:55 +00005210#define SIGNAL_SIMULATION 1
5211
5212PRE(pause)
5213{
5214 /* int pause(void); */
5215 MAYBE_PRINTF("pause ( )\n");
5216}
5217
5218PRE(rt_sigsuspend)
5219{
5220 /* int sigsuspend(const sigset_t *mask); */
5221 MAYBE_PRINTF("sigsuspend ( %p )\n", arg1 );
5222 if (arg1 != (Addr)NULL) {
5223 /* above NULL test is paranoia */
5224 SYSCALL_TRACK( pre_mem_read, tid, "sigsuspend(mask)", arg1,
5225 sizeof(vki_ksigset_t) );
5226 }
5227}
5228
5229PREALIAS(sigsuspend, rt_sigsuspend);
5230
5231PRE(rt_sigtimedwait)
5232{
5233 /* int sigtimedwait(const sigset_t *set, siginfo_t *info,
5234 const struct timespec timeout); */
nethercote9e7e7552003-11-01 14:03:37 +00005235 MAYBE_PRINTF("sigtimedwait ( %p, %p, timeout )\n", arg1, arg2);
5236 if (arg1 != (UInt)NULL)
5237 SYSCALL_TRACK( pre_mem_read, tid, "sigtimedwait(set)", arg1,
5238 sizeof(vki_ksigset_t));
jsgf855d93d2003-10-13 22:26:55 +00005239 if (arg2 != (UInt)NULL)
5240 SYSCALL_TRACK( pre_mem_write, tid, "sigtimedwait(info)", arg2,
5241 sizeof(siginfo_t) );
5242}
5243
5244POST(rt_sigtimedwait)
5245{
5246 if (arg2 != (UInt)NULL)
5247 VG_TRACK( post_mem_write, arg2, sizeof(siginfo_t) );
5248}
5249
5250PRE(rt_sigqueueinfo)
5251{
5252 /* long sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo) */
5253 MAYBE_PRINTF("rt_sigqueueinfo(%d, %d, %p)\n", arg1, arg2, arg3);
5254 if (arg2 != (UInt)NULL)
5255 SYSCALL_TRACK( pre_mem_read, tid, "sigqueueinfo(uinfo)", arg3,
5256 sizeof(siginfo_t) );
5257}
5258
5259POST(rt_sigqueueinfo)
5260{
5261 if (res >= 0 &&
5262 arg2 != 0 &&
5263 !VG_(is_sig_ign)(arg2) &&
5264 !VG_(ksigismember)(&tst->eff_sig_mask, arg2) &&
5265 arg1 == VG_(getpid)()) {
5266 VG_(proxy_waitsig)();
5267 }
5268}
5269
5270PRE(sigaltstack)
5271{
5272 /* int sigaltstack(const stack_t *ss, stack_t *oss); */
5273 MAYBE_PRINTF("sigaltstack ( %p, %p )\n",arg1,arg2);
5274 if (arg1 != (UInt)NULL) {
5275 SYSCALL_TRACK( pre_mem_read, tid, "sigaltstack(ss)",
5276 arg1, sizeof(vki_kstack_t) );
5277 }
5278 if (arg2 != (UInt)NULL) {
5279 SYSCALL_TRACK( pre_mem_write, tid, "sigaltstack(oss)",
5280 arg2, sizeof(vki_kstack_t) );
5281 }
5282
5283 if (SIGNAL_SIMULATION)
5284 VG_(do__NR_sigaltstack) (tid);
5285}
5286
5287POST(sigaltstack)
5288{
5289 if (res == 0 && arg2 != (UInt)NULL)
5290 VG_TRACK( post_mem_write, arg2, sizeof(vki_kstack_t));
5291}
5292
5293PRE(sigaction)
5294{
5295 /* int sigaction(int signum, struct k_sigaction *act,
5296 struct k_sigaction *oldact); */
5297 MAYBE_PRINTF("sigaction ( %d, %p, %p )\n",arg1,arg2,arg3);
5298 if (arg2 != (UInt)NULL)
5299 SYSCALL_TRACK( pre_mem_read, tid, "sigaction(act)",
5300 arg2, sizeof(vki_ksigaction));
5301 if (arg3 != (UInt)NULL)
5302 SYSCALL_TRACK( pre_mem_write, tid, "sigaction(oldact)",
5303 arg3, sizeof(vki_ksigaction));
5304
5305 if (SIGNAL_SIMULATION)
5306 VG_(do__NR_sigaction)(tid);
5307}
5308
5309POST(sigaction)
5310{
5311 if (res == 0 && arg3 != (UInt)NULL)
5312 VG_TRACK( post_mem_write, arg3, sizeof(vki_ksigaction));
5313}
5314
5315PREALIAS(rt_sigaction, sigaction);
5316POSTALIAS(rt_sigaction, sigaction);
5317
5318PRE(sigprocmask)
5319{
5320 /* int sigprocmask(int how, k_sigset_t *set,
5321 k_sigset_t *oldset); */
5322 MAYBE_PRINTF("sigprocmask ( %d, %p, %p )\n",arg1,arg2,arg3);
5323 if (arg2 != (UInt)NULL)
5324 SYSCALL_TRACK( pre_mem_read, tid, "sigprocmask(set)",
5325 arg2, sizeof(vki_ksigset_t));
5326 if (arg3 != (UInt)NULL)
5327 SYSCALL_TRACK( pre_mem_write, tid, "sigprocmask(oldset)",
5328 arg3, sizeof(vki_ksigset_t));
5329
5330 if (SIGNAL_SIMULATION)
5331 VG_(do__NR_sigprocmask) ( tid,
5332 arg1 /*how*/,
5333 (vki_ksigset_t*) arg2,
5334 (vki_ksigset_t*) arg3 );
5335}
5336
5337POST(sigprocmask)
5338{
5339 if (res == 0 && arg3 != (UInt)NULL)
5340 VG_TRACK( post_mem_write, arg3, sizeof(vki_ksigset_t));
5341}
5342
5343PREALIAS(rt_sigprocmask, sigprocmask);
5344POSTALIAS(rt_sigprocmask, sigprocmask);
5345
5346PRE(sigpending)
5347{
5348 /* int sigpending( sigset_t *set ) ; */
5349 MAYBE_PRINTF( "sigpending ( %p )\n", arg1 );
5350 SYSCALL_TRACK( pre_mem_write, tid, "sigpending(set)",
5351 arg1, sizeof(vki_ksigset_t));
5352}
5353
5354POST(sigpending)
5355{
nethercotefe082612004-07-10 18:08:13 +00005356 VG_TRACK( post_mem_write, arg1, sizeof( vki_ksigset_t ) ) ;
jsgf855d93d2003-10-13 22:26:55 +00005357}
5358
5359PREALIAS(rt_sigpending, sigpending);
5360POSTALIAS(rt_sigpending, sigpending);
5361
thughes9aaebc32004-07-15 23:13:37 +00005362PRE(io_setup)
5363{
5364 UInt size;
5365 Addr addr;
5366
5367 /* long io_setup (unsigned nr_events, aio_context_t *ctxp); */
5368 MAYBE_PRINTF("io_setup ( %ul, %p )\n",arg1,arg2);
5369 SYSCALL_TRACK( pre_mem_write, tid, "io_setup(ctxp)",
5370 arg2, sizeof(vki_aio_context_t) );
5371
5372 size = PGROUNDUP(sizeof(vki_aio_ring) + arg1 * sizeof(vki_io_event));
5373 addr = VG_(find_map_space)(0, size, True);
5374 VG_(map_segment)(addr, size, VKI_PROT_READ|VKI_PROT_EXEC, SF_FIXED);
5375
5376 VG_(pad_address_space)();
5377 res = VG_(do_syscall)(SYSNO, arg1, arg2);
5378 VG_(unpad_address_space)();
5379
5380 if (res == 0) {
5381 vki_aio_ring *r = *(vki_aio_ring **)arg2;
5382
5383 vg_assert(addr == (Addr)r);
5384 vg_assert(valid_client_addr(addr, size, tid, "io_setup"));
5385
5386 VG_TRACK( new_mem_mmap, addr, size, True, True, False );
5387 VG_TRACK( post_mem_write, arg2, sizeof(vki_aio_context_t) );
5388 }
5389 else {
5390 VG_(unmap_range)(addr, size);
5391 }
5392}
5393
5394PRE(io_destroy)
5395{
5396 Segment *s = VG_(find_segment)(arg1);
5397 vki_aio_ring *r = *(vki_aio_ring **)arg1;
5398 UInt size = PGROUNDUP(sizeof(vki_aio_ring) + r->nr * sizeof(vki_io_event));
5399
5400 /* long io_destroy (aio_context_t ctx); */
5401 MAYBE_PRINTF("io_destroy ( %ul )\n",arg1);
5402
5403 res = VG_(do_syscall)(SYSNO, arg1);
5404
5405 if (res == 0 && s != NULL && VG_(seg_contains)(s, arg1, size)) {
5406 VG_TRACK( die_mem_munmap, arg1, size );
5407 VG_(unmap_range)(arg1, size);
5408 }
5409}
5410
5411PRE(io_getevents)
5412{
5413 /* long io_getevents (aio_context_t ctx_id, long min_nr, long nr,
5414 struct io_event *events, struct timespec *timeout); */
5415 MAYBE_PRINTF("io_getevents ( %ul, %l, %l, %p, %p )\n",arg1,arg2,arg3,arg4,arg5);
5416 if (arg3 > 0)
5417 SYSCALL_TRACK( pre_mem_write, tid, "io_getevents(events)",
5418 arg4, sizeof(vki_io_event)*arg3 );
5419 if (arg5 != (UInt)NULL)
5420 SYSCALL_TRACK( pre_mem_read, tid, "io_getevents(timeout)",
5421 arg5, sizeof(struct timespec));
5422}
5423
5424POST(io_getevents)
5425{
5426 int i;
5427
5428 if (res > 0) {
5429 VG_TRACK( post_mem_write, arg4, sizeof(vki_io_event)*res );
5430 for (i = 0; i < res; i++) {
5431 const vki_io_event *vev = ((vki_io_event *)arg4) + i;
5432 const vki_iocb *cb = (vki_iocb *)(UInt)vev->obj;
5433
5434 switch (cb->aio_lio_opcode) {
5435 case VKI_IOCB_CMD_PREAD:
5436 if (vev->result > 0)
5437 VG_TRACK( post_mem_write, cb->aio_buf, vev->result );
5438 break;
5439
5440 case VKI_IOCB_CMD_PWRITE:
5441 break;
5442
5443 default:
5444 VG_(message)(Vg_DebugMsg,"Warning: unhandled io_getevents opcode: %u\n",cb->aio_lio_opcode);
5445 break;
5446 }
5447 }
5448 }
5449}
5450
5451PRE(io_submit)
5452{
5453 int i;
5454
5455 /* long io_submit (aio_context_t ctx_id, long nr, struct iocb **iocbpp); */
5456 MAYBE_PRINTF("io_submit( %ul, %l, %p )\n",arg1,arg2,arg3);
5457 SYSCALL_TRACK( pre_mem_read, tid, "io_submit(iocbpp)",
5458 arg3, sizeof(vki_iocb *)*arg2 );
5459 for (i = 0; i < arg2; i++) {
5460 vki_iocb *cb = ((vki_iocb **)arg3)[i];
5461 SYSCALL_TRACK( pre_mem_read, tid, "io_submit(iocb)",
5462 (UInt)cb, sizeof(vki_iocb) );
5463 switch (cb->aio_lio_opcode) {
5464 case VKI_IOCB_CMD_PREAD:
5465 SYSCALL_TRACK( pre_mem_write, tid, "io_submit(PREAD)",
5466 cb->aio_buf, cb->aio_nbytes );
5467 break;
5468
5469 case VKI_IOCB_CMD_PWRITE:
5470 SYSCALL_TRACK( pre_mem_read, tid, "io_submit(PWRITE)",
5471 cb->aio_buf, cb->aio_nbytes );
5472 break;
5473
5474 default:
5475 VG_(message)(Vg_DebugMsg,"Warning: unhandled io_submit opcode: %u\n",cb->aio_lio_opcode);
5476 break;
5477 }
5478 }
5479}
5480
5481PRE(io_cancel)
5482{
5483 /* long io_cancel (aio_context_t ctx_id, struct iocb *iocb,
5484 struct io_event *result); */
5485 MAYBE_PRINTF("io_cancel( %ul, %p, %p )\n",arg1,arg2,arg3);
5486 SYSCALL_TRACK( pre_mem_read, tid, "io_cancel(iocb)",
5487 arg2, sizeof(vki_iocb) );
5488 SYSCALL_TRACK( pre_mem_write, tid, "io_cancel(result)",
5489 arg3, sizeof(vki_io_event) );
5490}
5491
5492POST(io_cancel)
5493{
5494 VG_TRACK( post_mem_write, arg3, sizeof(vki_io_event) );
5495}
jsgf855d93d2003-10-13 22:26:55 +00005496
5497#undef SYSNO
5498#undef res
5499#undef arg1
5500#undef arg2
5501#undef arg3
5502#undef arg4
5503#undef arg5
5504#undef arg6
5505
5506struct sys_info {
thughesbaa46e52004-07-29 17:44:23 +00005507 UInt flags;
jsgf855d93d2003-10-13 22:26:55 +00005508 void (*before)(ThreadId tid, ThreadState *tst);
5509 void (*after)(ThreadId tid, ThreadState *tst);
5510};
thughesbaa46e52004-07-29 17:44:23 +00005511#define SYSB_(name, flags) [__NR_##name] = { flags, before_##name, NULL }
5512#define SYSBA(name, flags) [__NR_##name] = { flags, before_##name, after_##name }
jsgf855d93d2003-10-13 22:26:55 +00005513
5514static void bad_before(ThreadId tid, ThreadState *tst)
5515{
5516 VG_(message)
5517 (Vg_DebugMsg,"WARNING: unhandled syscall: %d", tst->m_eax);
fitzhardinge98abfc72003-12-16 02:05:15 +00005518 if (VG_(clo_verbosity) > 1) {
5519 ExeContext *ec = VG_(get_ExeContext)(tid);
5520 VG_(pp_ExeContext)(ec);
5521 }
jsgf855d93d2003-10-13 22:26:55 +00005522 VG_(message)
5523 (Vg_DebugMsg,"Do not panic. You may be able to fix this easily.");
5524 VG_(message)
5525 (Vg_DebugMsg,"Read the file README_MISSING_SYSCALL_OR_IOCTL.");
5526
5527 tst->m_eax = -VKI_ENOSYS;
5528}
5529
5530static void bad_after(ThreadId tid, ThreadState *tst)
5531{
5532}
5533
5534static const struct sys_info bad_sys = { False, bad_before, bad_after };
5535
5536static const struct sys_info special_sys[] = {
5537 /* special */
thughesbaa46e52004-07-29 17:44:23 +00005538 SYSB_(exit_group, 0),
5539 SYSB_(exit, 0),
5540 SYSB_(clone, 0),
jsgf855d93d2003-10-13 22:26:55 +00005541
thughesbaa46e52004-07-29 17:44:23 +00005542 SYSB_(modify_ldt, 0),
5543 SYSB_(set_thread_area, 0),
5544 SYSB_(get_thread_area, 0),
5545 SYSB_(set_tid_address, 0),
jsgf855d93d2003-10-13 22:26:55 +00005546
thughesbaa46e52004-07-29 17:44:23 +00005547 SYSB_(execve, 0),
5548 SYSB_(brk, 0),
5549 SYSB_(mmap, 0),
5550 SYSB_(mremap, 0),
fitzhardingee1c06d82003-10-30 07:21:44 +00005551
thughesbaa46e52004-07-29 17:44:23 +00005552 SYSB_(io_setup, 0),
5553 SYSB_(io_destroy, 0),
thughes9aaebc32004-07-15 23:13:37 +00005554
jsgf855d93d2003-10-13 22:26:55 +00005555#if SIGNAL_SIMULATION
thughesbaa46e52004-07-29 17:44:23 +00005556 SYSBA(sigaltstack, 0),
5557 SYSBA(rt_sigaction, 0),
5558 SYSBA(sigaction, 0),
5559 SYSBA(rt_sigprocmask, 0),
5560 SYSBA(sigprocmask, 0),
jsgf855d93d2003-10-13 22:26:55 +00005561#endif /* SIGNAL_SIMULATION */
5562};
5563#define MAX_SPECIAL_SYS (sizeof(special_sys)/sizeof(special_sys[0]))
5564
5565static const struct sys_info sys_info[] = {
thughesbaa46e52004-07-29 17:44:23 +00005566 SYSBA(ptrace, 0),
5567 SYSB_(mount, MayBlock),
5568 SYSB_(umount, 0),
jsgf855d93d2003-10-13 22:26:55 +00005569
thughesbaa46e52004-07-29 17:44:23 +00005570 SYSB_(setresgid, 0),
5571 SYSB_(vhangup, 0),
5572 SYSB_(iopl, 0),
jsgf855d93d2003-10-13 22:26:55 +00005573
thughesbaa46e52004-07-29 17:44:23 +00005574 SYSB_(setxattr, MayBlock),
5575 SYSB_(lsetxattr, MayBlock),
5576 SYSB_(fsetxattr, MayBlock),
5577 SYSBA(getxattr, MayBlock),
5578 SYSBA(lgetxattr, MayBlock),
5579 SYSBA(fgetxattr, MayBlock),
5580 SYSBA(listxattr, MayBlock),
5581 SYSBA(llistxattr, MayBlock),
5582 SYSBA(flistxattr, MayBlock),
5583 SYSB_(removexattr, MayBlock),
5584 SYSB_(lremovexattr, MayBlock),
5585 SYSB_(fremovexattr, MayBlock),
jsgf855d93d2003-10-13 22:26:55 +00005586
thughesbaa46e52004-07-29 17:44:23 +00005587 SYSB_(quotactl, 0),
5588 SYSBA(lookup_dcookie, 0),
jsgf855d93d2003-10-13 22:26:55 +00005589
thughesbaa46e52004-07-29 17:44:23 +00005590 SYSB_(truncate64, MayBlock),
5591 SYSB_(fdatasync, MayBlock),
5592 SYSB_(msync, MayBlock),
jsgf855d93d2003-10-13 22:26:55 +00005593
thughesbaa46e52004-07-29 17:44:23 +00005594 SYSBA(getpmsg, MayBlock),
5595 SYSB_(putpmsg, MayBlock),
jsgf855d93d2003-10-13 22:26:55 +00005596
thughesbaa46e52004-07-29 17:44:23 +00005597 SYSBA(syslog, MayBlock),
5598 SYSB_(personality, 0),
5599 SYSB_(chroot, 0),
5600 SYSB_(madvise, MayBlock),
5601 SYSB_(nice, 0),
5602 SYSB_(setresgid32, 0),
5603 SYSB_(setfsuid32, 0),
5604 SYSBA(_sysctl, 0),
jsgf855d93d2003-10-13 22:26:55 +00005605
thughesbaa46e52004-07-29 17:44:23 +00005606 SYSB_(sched_getscheduler, 0), /* ??? */
5607 SYSB_(sched_setscheduler, 0), /* ??? */
jsgf855d93d2003-10-13 22:26:55 +00005608
thughesbaa46e52004-07-29 17:44:23 +00005609 SYSB_(mlock, MayBlock),
5610 SYSB_(munlock, MayBlock),
5611 SYSB_(mlockall, MayBlock),
5612 SYSB_(munlockall, MayBlock),
jsgf855d93d2003-10-13 22:26:55 +00005613
thughesbaa46e52004-07-29 17:44:23 +00005614 SYSB_(sched_get_priority_max, 0), /* ??? */
5615 SYSB_(sched_get_priority_min, 0), /* ??? */
jsgf855d93d2003-10-13 22:26:55 +00005616
thughesbaa46e52004-07-29 17:44:23 +00005617 SYSB_(setpriority, 0),
5618 SYSB_(getpriority, 0),
jsgf855d93d2003-10-13 22:26:55 +00005619
thughesbaa46e52004-07-29 17:44:23 +00005620 SYSB_(setfsgid, 0),
5621 SYSB_(setregid, 0),
5622 SYSB_(setresuid, 0),
5623 SYSB_(setfsuid, 0),
jsgf855d93d2003-10-13 22:26:55 +00005624
thughesbaa46e52004-07-29 17:44:23 +00005625 SYSBA(sendfile, MayBlock),
5626 SYSBA(sendfile64, MayBlock),
5627 SYSB_(pwrite64, MayBlock),
5628 SYSB_(sync, MayBlock),
5629 SYSBA(fstatfs, 0),
5630 SYSB_(getsid, 0),
5631 SYSBA(pread64, MayBlock),
5632 SYSB_(mknod, 0),
5633 SYSB_(flock, MayBlock),
5634 SYSB_(init_module, MayBlock),
5635 SYSB_(ioperm, 0),
5636 SYSBA(capget, 0),
5637 SYSB_(capset, 0),
5638 SYSB_(access, 0),
5639 SYSB_(chdir, 0),
5640 SYSB_(chmod, 0),
5641 SYSB_(chown32, 0),
5642 SYSB_(lchown32, 0),
5643 SYSB_(chown, 0),
5644 SYSBA(close, 0),
5645 SYSBA(dup, 0),
5646 SYSBA(dup2, 0),
5647 SYSBA(fcntl, MayBlock),
5648 SYSB_(fchdir, 0),
5649 SYSB_(fchown32, 0),
5650 SYSB_(fchown, 0),
5651 SYSB_(fchmod, 0),
5652 SYSBA(fcntl64, MayBlock),
5653 SYSBA(fstat, 0),
5654 SYSBA(fork, 0),
5655 SYSB_(fsync, MayBlock),
5656 SYSB_(ftruncate, MayBlock),
5657 SYSB_(ftruncate64, MayBlock),
5658 SYSBA(getdents, MayBlock),
5659 SYSBA(getdents64, MayBlock),
5660 SYSBA(getgroups32, MayBlock),
5661 SYSBA(getgroups, 0),
5662 SYSBA(getcwd, 0),
5663 SYSB_(geteuid, 0),
5664 SYSB_(geteuid32, 0),
5665 SYSB_(getegid, 0),
5666 SYSB_(getegid32, 0),
5667 SYSB_(getgid, 0),
5668 SYSB_(getgid32, 0),
5669 SYSB_(getpid, 0),
5670 SYSB_(getpgid, 0),
5671 SYSB_(getpgrp, 0),
5672 SYSB_(getppid, 0),
5673 SYSBA(getresgid, 0),
5674 SYSBA(getresgid32, 0),
5675 SYSBA(getresuid, 0),
5676 SYSBA(getresuid32, 0),
5677 SYSBA(ugetrlimit, 0),
5678 SYSBA(getrlimit, 0),
5679 SYSBA(getrusage, 0),
5680 SYSBA(gettimeofday, 0),
5681 SYSB_(getuid, 0),
5682 SYSB_(getuid32, 0),
5683 SYSBA(ipc, MayBlock),
5684 SYSBA(ioctl, MayBlock),
5685 SYSBA(kill, 0),
5686 SYSB_(link, MayBlock),
5687 SYSB_(lseek, 0),
5688 SYSBA(_llseek, 0),
5689 SYSBA(lstat, 0),
5690 SYSBA(lstat64, 0),
5691 SYSB_(mkdir, MayBlock),
5692 SYSBA(mprotect, 0),
5693 SYSBA(munmap, 0),
5694 SYSBA(mincore, 0),
5695 SYSBA(nanosleep, MayBlock|PostOnFail),
5696 SYSB_(_newselect, MayBlock),
5697 SYSBA(open, MayBlock),
5698 SYSBA(read, MayBlock),
5699 SYSB_(write, MayBlock),
5700 SYSBA(creat, MayBlock),
5701 SYSBA(pipe, 0),
5702 SYSBA(poll, MayBlock),
5703 SYSBA(epoll_create, 0),
5704 SYSB_(epoll_ctl, 0),
5705 SYSBA(epoll_wait, MayBlock),
5706 SYSBA(readlink, 0),
5707 SYSBA(readv, MayBlock),
5708 SYSB_(rename, 0),
5709 SYSB_(rmdir, MayBlock),
5710 SYSBA(sched_setparam, 0), /* ??? */
5711 SYSBA(sched_getparam, 0), /* ??? */
5712 SYSB_(sched_yield, 0), /* ??? */
5713 SYSB_(select, MayBlock),
5714 SYSB_(setfsgid32, 0),
5715 SYSB_(setgid32, 0),
5716 SYSB_(setgid, 0),
5717 SYSB_(setsid, 0),
5718 SYSB_(setgroups32, 0),
5719 SYSB_(setgroups, 0),
5720 SYSBA(setpgid, 0),
5721 SYSB_(setregid32, 0),
5722 SYSB_(setresuid32, 0),
5723 SYSB_(setreuid32, 0),
5724 SYSB_(setreuid, 0),
5725 SYSB_(setrlimit, 0),
5726 SYSB_(setuid32, 0),
5727 SYSB_(setuid, 0),
5728 SYSBA(socketcall, MayBlock),
5729 SYSBA(stat, 0),
5730 SYSBA(statfs, 0),
5731 SYSBA(statfs64, 0),
5732 SYSB_(symlink, MayBlock),
5733 SYSBA(stat64, 0),
5734 SYSBA(fstat64, 0),
5735 SYSBA(sysinfo, 0),
5736 SYSBA(time, 0),
5737 SYSBA(times, 0),
5738 SYSB_(truncate, MayBlock),
5739 SYSB_(umask, 0),
5740 SYSB_(unlink, MayBlock),
5741 SYSBA(uname, 0),
5742 SYSB_(utime, MayBlock),
5743 SYSB_(utimes, 0),
5744 SYSBA(waitpid, MayBlock),
5745 SYSBA(wait4, MayBlock),
5746 SYSB_(writev, MayBlock),
5747 SYSB_(prctl, MayBlock),
5748 SYSBA(adjtimex, 0),
5749 SYSBA(mmap2, 0),
5750 SYSBA(clock_gettime, 0),
5751 SYSBA(futex, MayBlock),
5752 SYSB_(acct, 0),
jsgf855d93d2003-10-13 22:26:55 +00005753
5754 /* new signal handling makes these normal blocking syscalls */
thughesbaa46e52004-07-29 17:44:23 +00005755 SYSB_(pause, MayBlock),
5756 SYSB_(sigsuspend, MayBlock),
5757 SYSB_(rt_sigsuspend, MayBlock),
5758 SYSBA(rt_sigtimedwait, MayBlock),
5759 SYSBA(rt_sigqueueinfo, 0),
fitzhardingea09a1b52003-11-07 23:09:48 +00005760
thughesbaa46e52004-07-29 17:44:23 +00005761 SYSBA(sigpending, MayBlock), /* not blocking, but must run in LWP context */
5762 SYSBA(rt_sigpending, MayBlock), /* not blocking, but must run in LWP context */
5763 SYSB_(alarm, MayBlock), /* not blocking, but must run in LWP context */
5764 SYSBA(setitimer, MayBlock), /* not blocking, but must run in LWP context */
5765 SYSBA(getitimer, MayBlock), /* not blocking, but must run in LWP context */
jsgf855d93d2003-10-13 22:26:55 +00005766
thughesbaa46e52004-07-29 17:44:23 +00005767 SYSBA(io_getevents, MayBlock),
5768 SYSB_(io_submit, 0),
5769 SYSBA(io_cancel, 0),
thughes9aaebc32004-07-15 23:13:37 +00005770
jsgf855d93d2003-10-13 22:26:55 +00005771#if !SIGNAL_SIMULATION
thughesbaa46e52004-07-29 17:44:23 +00005772 SYSBA(sigaltstack, 0),
5773 SYSBA(rt_sigaction, 0),
5774 SYSBA(sigaction, 0),
5775 SYSBA(rt_sigprocmask, 0),
5776 SYSBA(sigprocmask, 0),
jsgf855d93d2003-10-13 22:26:55 +00005777#endif /* !SIGNAL_SIMULATION */
5778};
5779#define MAX_SYS_INFO (sizeof(sys_info)/sizeof(sys_info[0]))
5780
5781#undef SYSB_
5782#undef SYSBA
5783
5784Bool VG_(pre_syscall) ( ThreadId tid )
sewardjde4a1d02002-03-22 01:27:54 +00005785{
sewardj018f7622002-05-15 21:13:39 +00005786 ThreadState* tst;
jsgf855d93d2003-10-13 22:26:55 +00005787 UInt syscallno;
5788 const struct sys_info *sys;
5789 Bool special = False;
5790 Bool syscall_done = False; /* we actually ran the syscall */
sewardjde4a1d02002-03-22 01:27:54 +00005791
njn25e49d8e72002-09-23 09:36:25 +00005792 VGP_PUSHCC(VgpCoreSysWrap);
sewardjde4a1d02002-03-22 01:27:54 +00005793
jsgf855d93d2003-10-13 22:26:55 +00005794 tst = VG_(get_ThreadState)(tid);
sewardj018f7622002-05-15 21:13:39 +00005795
jsgf855d93d2003-10-13 22:26:55 +00005796 /* Convert vfork to fork, since we can't handle it otherwise. */
5797 if (tst->m_eax == __NR_vfork)
5798 tst->m_eax = __NR_fork;
sewardjde4a1d02002-03-22 01:27:54 +00005799
jsgf855d93d2003-10-13 22:26:55 +00005800 syscallno = tst->m_eax;
5801
5802 if (tst->syscallno != -1)
5803 VG_(printf)("tid %d has syscall %d\n", tst->tid, tst->syscallno);
5804
5805 vg_assert(tst->syscallno == -1); /* should be no current syscall */
5806 vg_assert(tst->status == VgTs_Runnable); /* should be runnable */
5807
5808 /* the syscall no is in %eax. For syscalls with <= 6 args,
5809 args 1 .. 6 to the syscall are in %ebx %ecx %edx %esi %edi %ebp.
5810 For calls with > 6 args, %ebx points to a lump of memory
sewardjde4a1d02002-03-22 01:27:54 +00005811 containing the args.
5812
5813 The result is returned in %eax. If this value >= 0, the call
5814 succeeded, and this is the return value. If < 0, it failed, and
5815 the negation of this value is errno. To be more specific,
5816 if res is in the range -EMEDIUMTYPE (-124) .. -EPERM (-1)
5817 (kernel 2.4.9 sources, include/asm-i386/errno.h)
5818 then it indicates an error. Otherwise it doesn't.
5819
5820 Dirk Mueller (mueller@kde.org) says that values -4095 .. -1
5821 (inclusive?) indicate error returns. Not sure where the -4095
5822 comes from.
5823 */
5824
jsgf855d93d2003-10-13 22:26:55 +00005825 tst->syscallno = syscallno;
fitzhardingef0f911c2003-11-09 09:51:33 +00005826 vg_assert(tst->status == VgTs_Runnable);
sewardjde4a1d02002-03-22 01:27:54 +00005827
jsgf855d93d2003-10-13 22:26:55 +00005828 if (syscallno < MAX_SPECIAL_SYS && special_sys[syscallno].before != NULL) {
5829 sys = &special_sys[syscallno];
5830 special = True;
5831 } else if (syscallno < MAX_SYS_INFO && sys_info[syscallno].before != NULL) {
5832 sys = &sys_info[syscallno];
5833 } else {
5834 sys = &bad_sys;
5835 special = True;
sewardjde4a1d02002-03-22 01:27:54 +00005836 }
5837
thughesbaa46e52004-07-29 17:44:23 +00005838 tst->sys_flags = sys->flags;
5839
jsgf855d93d2003-10-13 22:26:55 +00005840 /* Do any pre-syscall actions */
5841 if (VG_(needs).syscall_wrapper) {
5842 VGP_PUSHCC(VgpSkinSysWrap);
thughesbaa46e52004-07-29 17:44:23 +00005843 tst->sys_pre_res = SK_(pre_syscall)(tid, syscallno, /*isBlocking*/(sys->flags & MayBlock) != 0);
jsgf855d93d2003-10-13 22:26:55 +00005844 VGP_POPCC(VgpSkinSysWrap);
5845 }
5846
5847 MAYBE_PRINTF("SYSCALL[%d,%d](%3d)%s%s:",
5848 VG_(getpid)(), tid, syscallno,
5849 special ? " special" : "",
thughesbaa46e52004-07-29 17:44:23 +00005850 (sys->flags & MayBlock) != 0 ? " blocking" : "");
jsgf855d93d2003-10-13 22:26:55 +00005851
5852 if (special) {
5853 /* "Special" syscalls are implemented by Valgrind internally,
5854 and do not generate real kernel calls. The expectation,
5855 therefore, is that the "before" function not only does the
5856 appropriate tests, but also performs the syscall itself and
5857 sets the result. Special syscalls cannot block. */
thughesbaa46e52004-07-29 17:44:23 +00005858 vg_assert((tst->sys_flags & MayBlock) == 0);
jsgf855d93d2003-10-13 22:26:55 +00005859
5860 (sys->before)(tst->tid, tst);
5861
thughesbaa46e52004-07-29 17:44:23 +00005862 vg_assert(tst->sys_flags == sys->flags);
5863
jsgf855d93d2003-10-13 22:26:55 +00005864 syscall_done = True;
5865 } else {
5866 (sys->before)(tst->tid, tst);
5867
5868 if ((Int)tst->m_eax <= 0) {
5869 /* "before" decided the syscall wasn't viable, so don't do
5870 anything - just pretend the syscall happened. */
5871 syscall_done = True;
thughesbaa46e52004-07-29 17:44:23 +00005872 } else if ((tst->sys_flags & MayBlock) != 0) {
fitzhardinge33730212003-11-10 21:21:00 +00005873 /* Issue to worker. If we're waiting on the syscall because
5874 it's in the hands of the ProxyLWP, then set the thread
5875 state to WaitSys. */
5876 tst->status = VgTs_WaitSys;
jsgf855d93d2003-10-13 22:26:55 +00005877 VG_(sys_issue)(tid);
5878 } else {
5879 /* run the syscall directly */
5880 tst->m_eax = VG_(do_syscall)(syscallno,
5881 tst->m_ebx,
5882 tst->m_ecx,
5883 tst->m_edx,
5884 tst->m_esi,
5885 tst->m_edi,
5886 tst->m_ebp);
5887 syscall_done = True;
5888 }
5889 }
5890
5891 VGP_POPCC(VgpCoreSysWrap);
5892
fitzhardinge33730212003-11-10 21:21:00 +00005893 vg_assert(( syscall_done && tst->status == VgTs_Runnable) ||
5894 (!syscall_done && tst->status == VgTs_WaitSys ));
fitzhardingef0f911c2003-11-09 09:51:33 +00005895
jsgf855d93d2003-10-13 22:26:55 +00005896 return syscall_done;
5897}
5898
5899
fitzhardinge31ba9052004-01-16 02:15:23 +00005900void VG_(post_syscall) ( ThreadId tid, Bool restart )
jsgf855d93d2003-10-13 22:26:55 +00005901{
5902 ThreadState* tst;
5903 UInt syscallno;
5904 const struct sys_info *sys;
5905 Bool special = False;
fitzhardinge31ba9052004-01-16 02:15:23 +00005906 Bool restarted = False;
jsgf855d93d2003-10-13 22:26:55 +00005907 void *pre_res;
5908
5909 VGP_PUSHCC(VgpCoreSysWrap);
5910
5911 tst = VG_(get_ThreadState)(tid);
5912
5913 /* Tell the skin about the syscall return value */
5914 SET_SYSCALL_RETVAL(tst->tid, tst->m_eax);
5915
5916 syscallno = tst->syscallno;
5917 pre_res = tst->sys_pre_res;
5918
5919 vg_assert(syscallno != -1); /* must be a current syscall */
jsgf855d93d2003-10-13 22:26:55 +00005920
5921 if (syscallno < MAX_SPECIAL_SYS && special_sys[syscallno].before != NULL) {
5922 sys = &special_sys[syscallno];
5923 special = True;
5924 } else if (syscallno < MAX_SYS_INFO && sys_info[syscallno].before != NULL) {
5925 sys = &sys_info[syscallno];
5926 } else {
5927 sys = &bad_sys;
5928 special = True;
5929 }
fitzhardingef0f911c2003-11-09 09:51:33 +00005930
fitzhardingee1c06d82003-10-30 07:21:44 +00005931 if (tst->m_eax == -VKI_ERESTARTSYS) {
fitzhardinge31ba9052004-01-16 02:15:23 +00005932 /* Applications never expect to see this, so we should either
5933 restart the syscall or fail it with EINTR, depending on what
5934 our caller wants. Generally they'll want to restart, but if
5935 client set the signal state to not restart, then we fail with
5936 EINTR. Either way, ERESTARTSYS means the syscall made no
5937 progress, and so can be failed or restarted without
5938 consequence. */
5939 if (0)
5940 VG_(printf)("syscall %d returned ERESTARTSYS; restart=%d\n",
5941 syscallno, restart);
5942
5943 if (restart) {
5944 restarted = True;
5945 VG_(restart_syscall)(tid);
5946 } else
5947 tst->m_eax = -VKI_EINTR;
5948 }
5949
5950 if (!restarted) {
thughesbaa46e52004-07-29 17:44:23 +00005951 if (sys->after != NULL &&
5952 ((tst->sys_flags & PostOnFail) != 0 || !VG_(is_kerror)(tst->m_eax)))
fitzhardinge31ba9052004-01-16 02:15:23 +00005953 (sys->after)(tst->tid, tst);
5954
5955 /* Do any post-syscall actions
5956
5957 NOTE: this is only called if the syscall completed. If the
5958 syscall was restarted, then it will call the Tool's
5959 pre_syscall again, without calling post_syscall (ie, more
5960 pre's than post's)
5961 */
5962 if (VG_(needs).syscall_wrapper) {
5963 VGP_PUSHCC(VgpSkinSysWrap);
5964 SK_(post_syscall)(tid, syscallno, pre_res, tst->m_eax, /*isBlocking*/True); // did block
5965 VGP_POPCC(VgpSkinSysWrap);
5966 }
fitzhardingee1c06d82003-10-30 07:21:44 +00005967 }
5968
jsgf855d93d2003-10-13 22:26:55 +00005969 tst->status = VgTs_Runnable; /* runnable again */
fitzhardinge31ba9052004-01-16 02:15:23 +00005970 tst->syscallno = -1; /* no current syscall */
sewardj2e93c502002-04-12 11:12:52 +00005971
njn25e49d8e72002-09-23 09:36:25 +00005972 VGP_POPCC(VgpCoreSysWrap);
sewardj2e93c502002-04-12 11:12:52 +00005973}
5974
fitzhardingee1c06d82003-10-30 07:21:44 +00005975void VG_(restart_syscall)(ThreadId tid)
5976{
5977 ThreadState* tst;
5978 tst = VG_(get_ThreadState)(tid);
5979
5980 vg_assert(tst != NULL);
5981 vg_assert(tst->status == VgTs_WaitSys);
5982 vg_assert(tst->syscallno != -1);
5983
5984 tst->m_eax = tst->syscallno;
5985 tst->m_eip -= 2; /* sizeof(int $0x80) */
fitzhardingea09a1b52003-11-07 23:09:48 +00005986
5987 /* Make sure our caller is actually sane, and we're really backing
5988 back over a syscall.
5989
5990 int $0x80 == CD 80
5991 */
5992 {
5993 UChar *p = (UChar *)tst->m_eip;
5994
5995 if (p[0] != 0xcd || p[1] != 0x80)
5996 VG_(message)(Vg_DebugMsg,
5997 "?! restarting over syscall at %p %02x %02x\n",
5998 tst->m_eip, p[0], p[1]);
5999
6000 vg_assert(p[0] == 0xcd && p[1] == 0x80);
6001 }
fitzhardingee1c06d82003-10-30 07:21:44 +00006002}
sewardj2e93c502002-04-12 11:12:52 +00006003
sewardjde4a1d02002-03-22 01:27:54 +00006004/*--------------------------------------------------------------------*/
njn87ef6a62003-08-14 15:23:55 +00006005/*--- end vg_syscalls.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00006006/*--------------------------------------------------------------------*/
njnb94b81e2003-09-09 11:27:59 +00006007