blob: ab489a59367450b9f4e2c1cdb5d730aec84fb155 [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
njn0e1b5142003-04-15 14:58:06 +000010 Copyright (C) 2000-2003 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
njn25e49d8e72002-09-23 09:36:25 +0000120/* ---------------------------------------------------------------------
121 Doing mmap, munmap, mremap, mprotect
122 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000123
njn25e49d8e72002-09-23 09:36:25 +0000124// Nb: this isn't done as precisely as possible, but it seems that programs
125// are usually sufficiently well-behaved that the more obscure corner cases
126// aren't important. Various comments in the few functions below give more
127// details... njn 2002-Sep-17
128
129/* AFAICT from kernel sources (mm/mprotect.c) and general experimentation,
130 munmap, mprotect (and mremap??) work at the page level. So addresses
131 and lengths must be adjusted for this. */
132
133/* Mash around start and length so that the area exactly covers
134 an integral number of pages. If we don't do that, memcheck's
135 idea of addressible memory diverges from that of the
136 kernel's, which causes the leak detector to crash. */
137static
138void mash_addr_and_len( Addr* a, UInt* len)
sewardjde4a1d02002-03-22 01:27:54 +0000139{
njn25e49d8e72002-09-23 09:36:25 +0000140 while (( *a % VKI_BYTES_PER_PAGE) > 0) { (*a)--; (*len)++; }
141 while (((*a + *len) % VKI_BYTES_PER_PAGE) > 0) { (*len)++; }
sewardjde4a1d02002-03-22 01:27:54 +0000142}
143
144static
njn25e49d8e72002-09-23 09:36:25 +0000145void mmap_segment ( Addr a, UInt len, UInt prot, Int fd )
sewardjde4a1d02002-03-22 01:27:54 +0000146{
sewardj40f8ebe2002-10-23 21:46:13 +0000147 Bool rr, ww, xx;
njn25e49d8e72002-09-23 09:36:25 +0000148
149 /* Records segment, reads debug symbols if necessary */
sewardj1806d7f2002-10-22 05:05:49 +0000150 if ((prot & PROT_EXEC) && fd != -1)
njnfa1016e2003-09-25 17:54:11 +0000151 VG_(new_exeseg_mmap) ( a, len );
njn25e49d8e72002-09-23 09:36:25 +0000152
njn25e49d8e72002-09-23 09:36:25 +0000153 rr = prot & PROT_READ;
154 ww = prot & PROT_WRITE;
155 xx = prot & PROT_EXEC;
156
sewardj40f8ebe2002-10-23 21:46:13 +0000157 VG_TRACK( new_mem_mmap, a, len, rr, ww, xx );
sewardjde4a1d02002-03-22 01:27:54 +0000158}
159
160static
njn25e49d8e72002-09-23 09:36:25 +0000161void munmap_segment ( Addr a, UInt len )
sewardjde4a1d02002-03-22 01:27:54 +0000162{
njn25e49d8e72002-09-23 09:36:25 +0000163 /* Addr orig_a = a;
164 Addr orig_len = len; */
sewardjde4a1d02002-03-22 01:27:54 +0000165
njn25e49d8e72002-09-23 09:36:25 +0000166 mash_addr_and_len(&a, &len);
167 /*
168 VG_(printf)("MUNMAP: correct (%p for %d) to (%p for %d) %s\n",
169 orig_a, orig_len, a, len, (orig_a!=start || orig_len!=length)
170 ? "CHANGE" : "");
sewardjde4a1d02002-03-22 01:27:54 +0000171 */
njn25e49d8e72002-09-23 09:36:25 +0000172
173 /* Invalidate translations as necessary (also discarding any basic
174 block-specific info retained by the skin) and unload any debug
175 symbols. */
176 // This doesn't handle partial unmapping of exe segs correctly, if that
177 // ever happens...
njnfa1016e2003-09-25 17:54:11 +0000178 VG_(remove_if_exeseg) ( a, len );
njn25e49d8e72002-09-23 09:36:25 +0000179
180 VG_TRACK( die_mem_munmap, a, len );
sewardjde4a1d02002-03-22 01:27:54 +0000181}
182
njn25e49d8e72002-09-23 09:36:25 +0000183static
184void mprotect_segment ( Addr a, UInt len, Int prot )
sewardjde4a1d02002-03-22 01:27:54 +0000185{
sewardj40f8ebe2002-10-23 21:46:13 +0000186 Bool rr, ww, xx;
187
njn25e49d8e72002-09-23 09:36:25 +0000188 rr = prot & PROT_READ;
189 ww = prot & PROT_WRITE;
190 xx = prot & PROT_EXEC;
191
192 // if removing exe permission, should check and remove from exe_seg list
193 // if adding, should check and add to exe_seg list
194 // easier to ignore both cases -- both v. unlikely?
195 mash_addr_and_len(&a, &len);
sewardj40f8ebe2002-10-23 21:46:13 +0000196 VG_TRACK( change_mem_mprotect, a, len, rr, ww, xx );
njn25e49d8e72002-09-23 09:36:25 +0000197}
198
199static
njn39209d42003-06-13 15:02:29 +0000200void mremap_segment ( Addr old_addr, UInt old_size, Addr new_addr,
201 UInt new_size )
njn25e49d8e72002-09-23 09:36:25 +0000202{
203 /* If the block moves, assume new and old blocks can't overlap; seems to
204 * be valid judging from Linux kernel code in mm/mremap.c */
205 vg_assert(old_addr == new_addr ||
206 old_addr+old_size < new_addr ||
207 new_addr+new_size < old_addr);
208
209 if (new_size < old_size) {
210 // if exe_seg
211 // unmap old symbols from old_addr+new_size..old_addr+new_size
212 // update exe_seg size = new_size
213 // update exe_seg addr = new_addr...
214 VG_TRACK( copy_mem_remap, old_addr, new_addr, new_size );
215 VG_TRACK( die_mem_munmap, old_addr+new_size, old_size-new_size );
216
217 } else {
218 // if exe_seg
219 // map new symbols from new_addr+old_size..new_addr+new_size
220 // update exe_seg size = new_size
221 // update exe_seg addr = new_addr...
222 VG_TRACK( copy_mem_remap, old_addr, new_addr, old_size );
223 // what should the permissions on the new extended part be??
224 // using 'rwx'
225 VG_TRACK( new_mem_mmap, new_addr+old_size, new_size-old_size,
sewardj40f8ebe2002-10-23 21:46:13 +0000226 True, True, True );
njn25e49d8e72002-09-23 09:36:25 +0000227 }
sewardjde4a1d02002-03-22 01:27:54 +0000228}
229
230
231/* Is this a Linux kernel error return value? */
232/* From:
233 http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/sysdeps/unix/sysv/
234 linux/i386/sysdep.h?
235 rev=1.28&content-type=text/x-cvsweb-markup&cvsroot=glibc
236
njn25e49d8e72002-09-23 09:36:25 +0000237 \begin{quote}:
sewardjde4a1d02002-03-22 01:27:54 +0000238
239 Linux uses a negative return value to indicate syscall errors,
240 unlike most Unices, which use the condition codes' carry flag.
241
242 Since version 2.1 the return value of a system call might be
243 negative even if the call succeeded. E.g., the `lseek' system call
244 might return a large offset. Therefore we must not anymore test
245 for < 0, but test for a real error by making sure the value in %eax
246 is a real error number. Linus said he will make sure the no syscall
daywalker7e73e5f2003-07-04 16:18:15 +0000247 returns a value in -1 .. -4095 as a valid result so we can safely
sewardjde4a1d02002-03-22 01:27:54 +0000248 test with -4095.
249
250 END QUOTE
251*/
252Bool VG_(is_kerror) ( Int res )
253{
254 if (res >= -4095 && res <= -1)
255 return True;
256 else
257 return False;
258}
259
260static
261UInt get_shm_size ( Int shmid )
262{
263 struct shmid_ds buf;
jsgf855d93d2003-10-13 22:26:55 +0000264 long __res = VG_(do_syscall)(__NR_ipc, 24 /* IPCOP_shmctl */, shmid, IPC_STAT, 0, &buf);
sewardjde4a1d02002-03-22 01:27:54 +0000265 if ( VG_(is_kerror) ( __res ) )
266 return 0;
267
268 return buf.shm_segsz;
269}
270
271static
sewardj8c824512002-04-14 04:16:48 +0000272Char *strdupcat ( const Char *s1, const Char *s2, ArenaId aid )
sewardjde4a1d02002-03-22 01:27:54 +0000273{
274 UInt len = VG_(strlen) ( s1 ) + VG_(strlen) ( s2 ) + 1;
njn25e49d8e72002-09-23 09:36:25 +0000275 Char *result = VG_(arena_malloc) ( aid, len );
sewardjde4a1d02002-03-22 01:27:54 +0000276 VG_(strcpy) ( result, s1 );
277 VG_(strcat) ( result, s2 );
278 return result;
279}
280
281static
jsgf855d93d2003-10-13 22:26:55 +0000282void pre_mem_read_sendmsg ( ThreadId tid,
283 Char *msg, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +0000284{
285 Char *outmsg = strdupcat ( "socketcall.sendmsg", msg, VG_AR_TRANSIENT );
njn72718642003-07-24 08:45:32 +0000286 SYSCALL_TRACK( pre_mem_read, tid, outmsg, base, size );
njn25e49d8e72002-09-23 09:36:25 +0000287
288 VG_(arena_free) ( VG_AR_TRANSIENT, outmsg );
sewardjde4a1d02002-03-22 01:27:54 +0000289}
290
291static
jsgf855d93d2003-10-13 22:26:55 +0000292void pre_mem_write_recvmsg ( ThreadId tid,
293 Char *msg, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +0000294{
295 Char *outmsg = strdupcat ( "socketcall.recvmsg", msg, VG_AR_TRANSIENT );
njn72718642003-07-24 08:45:32 +0000296 SYSCALL_TRACK( pre_mem_write, tid, outmsg, base, size );
njn25e49d8e72002-09-23 09:36:25 +0000297 VG_(arena_free) ( VG_AR_TRANSIENT, outmsg );
sewardjde4a1d02002-03-22 01:27:54 +0000298}
299
300static
njn72718642003-07-24 08:45:32 +0000301void post_mem_write_recvmsg ( ThreadId tid,
njn25e49d8e72002-09-23 09:36:25 +0000302 Char *fieldName, UInt base, UInt size )
sewardjde4a1d02002-03-22 01:27:54 +0000303{
njn25e49d8e72002-09-23 09:36:25 +0000304 VG_TRACK( post_mem_write, base, size );
sewardjde4a1d02002-03-22 01:27:54 +0000305}
306
307static
sewardj8c824512002-04-14 04:16:48 +0000308void msghdr_foreachfield (
njn72718642003-07-24 08:45:32 +0000309 ThreadId tid,
sewardj8c824512002-04-14 04:16:48 +0000310 struct msghdr *msg,
njn72718642003-07-24 08:45:32 +0000311 void (*foreach_func)( ThreadId, Char *, UInt, UInt )
sewardj8c824512002-04-14 04:16:48 +0000312 )
sewardjde4a1d02002-03-22 01:27:54 +0000313{
314 if ( !msg )
315 return;
316
njn72718642003-07-24 08:45:32 +0000317 foreach_func ( tid, "(msg)", (Addr)msg, sizeof( struct msghdr ) );
sewardjde4a1d02002-03-22 01:27:54 +0000318
319 if ( msg->msg_name )
njn72718642003-07-24 08:45:32 +0000320 foreach_func ( tid,
sewardj8c824512002-04-14 04:16:48 +0000321 "(msg.msg_name)",
sewardjde4a1d02002-03-22 01:27:54 +0000322 (Addr)msg->msg_name, msg->msg_namelen );
323
324 if ( msg->msg_iov ) {
325 struct iovec *iov = msg->msg_iov;
326 UInt i;
327
njn72718642003-07-24 08:45:32 +0000328 foreach_func ( tid,
sewardj8c824512002-04-14 04:16:48 +0000329 "(msg.msg_iov)",
sewardjde4a1d02002-03-22 01:27:54 +0000330 (Addr)iov, msg->msg_iovlen * sizeof( struct iovec ) );
331
332 for ( i = 0; i < msg->msg_iovlen; ++i, ++iov )
njn72718642003-07-24 08:45:32 +0000333 foreach_func ( tid,
sewardj8c824512002-04-14 04:16:48 +0000334 "(msg.msg_iov[i]",
sewardjde4a1d02002-03-22 01:27:54 +0000335 (Addr)iov->iov_base, iov->iov_len );
336 }
337
338 if ( msg->msg_control )
njn72718642003-07-24 08:45:32 +0000339 foreach_func ( tid,
sewardj8c824512002-04-14 04:16:48 +0000340 "(msg.msg_control)",
sewardjde4a1d02002-03-22 01:27:54 +0000341 (Addr)msg->msg_control, msg->msg_controllen );
342}
343
sewardjc483e8f2002-05-03 21:01:35 +0000344static
jsgf855d93d2003-10-13 22:26:55 +0000345void pre_mem_read_sockaddr ( ThreadId tid,
346 Char *description,
347 struct sockaddr *sa, UInt salen )
sewardjc483e8f2002-05-03 21:01:35 +0000348{
sewardjff7c1ab2003-02-24 21:55:34 +0000349 Char *outmsg;
350
351 /* NULL/zero-length sockaddrs are legal */
352 if ( sa == NULL || salen == 0 ) return;
353
354 outmsg = VG_(arena_malloc) ( VG_AR_TRANSIENT,
355 strlen( description ) + 30 );
sewardjc483e8f2002-05-03 21:01:35 +0000356
357 VG_(sprintf) ( outmsg, description, ".sa_family" );
njn72718642003-07-24 08:45:32 +0000358 SYSCALL_TRACK( pre_mem_read, tid, outmsg,
sewardj09cbb222002-11-17 02:46:19 +0000359 (UInt) &sa->sa_family, sizeof (sa_family_t));
jsgf855d93d2003-10-13 22:26:55 +0000360
sewardjc483e8f2002-05-03 21:01:35 +0000361 switch (sa->sa_family) {
362
363 case AF_UNIX:
364 VG_(sprintf) ( outmsg, description, ".sun_path" );
njn72718642003-07-24 08:45:32 +0000365 SYSCALL_TRACK( pre_mem_read_asciiz, tid, outmsg,
sewardjc483e8f2002-05-03 21:01:35 +0000366 (UInt) ((struct sockaddr_un *) sa)->sun_path);
367 break;
368
369 case AF_INET:
370 VG_(sprintf) ( outmsg, description, ".sin_port" );
njn72718642003-07-24 08:45:32 +0000371 SYSCALL_TRACK( pre_mem_read, tid, outmsg,
sewardjc483e8f2002-05-03 21:01:35 +0000372 (UInt) &((struct sockaddr_in *) sa)->sin_port,
sewardj32102152002-05-04 10:28:17 +0000373 sizeof (((struct sockaddr_in *) sa)->sin_port));
sewardjc483e8f2002-05-03 21:01:35 +0000374 VG_(sprintf) ( outmsg, description, ".sin_addr" );
njn72718642003-07-24 08:45:32 +0000375 SYSCALL_TRACK( pre_mem_read, tid, outmsg,
sewardjc483e8f2002-05-03 21:01:35 +0000376 (UInt) &((struct sockaddr_in *) sa)->sin_addr,
377 sizeof (struct in_addr));
378 break;
379
380 case AF_INET6:
381 VG_(sprintf) ( outmsg, description, ".sin6_port" );
njn72718642003-07-24 08:45:32 +0000382 SYSCALL_TRACK( pre_mem_read, tid, outmsg,
sewardjc483e8f2002-05-03 21:01:35 +0000383 (UInt) &((struct sockaddr_in6 *) sa)->sin6_port,
sewardj32102152002-05-04 10:28:17 +0000384 sizeof (((struct sockaddr_in6 *) sa)->sin6_port));
sewardjc483e8f2002-05-03 21:01:35 +0000385 VG_(sprintf) ( outmsg, description, ".sin6_flowinfo" );
njn72718642003-07-24 08:45:32 +0000386 SYSCALL_TRACK( pre_mem_read, tid, outmsg,
sewardjc483e8f2002-05-03 21:01:35 +0000387 (UInt) &((struct sockaddr_in6 *) sa)->sin6_flowinfo,
388 sizeof (uint32_t));
389 VG_(sprintf) ( outmsg, description, ".sin6_addr" );
njn72718642003-07-24 08:45:32 +0000390 SYSCALL_TRACK( pre_mem_read, tid, outmsg,
sewardjc483e8f2002-05-03 21:01:35 +0000391 (UInt) &((struct sockaddr_in6 *) sa)->sin6_addr,
392 sizeof (struct in6_addr));
sewardj32102152002-05-04 10:28:17 +0000393# ifndef GLIBC_2_1
sewardjc483e8f2002-05-03 21:01:35 +0000394 VG_(sprintf) ( outmsg, description, ".sin6_scope_id" );
njn72718642003-07-24 08:45:32 +0000395 SYSCALL_TRACK( pre_mem_read, tid, outmsg,
sewardjc483e8f2002-05-03 21:01:35 +0000396 (UInt) &((struct sockaddr_in6 *) sa)->sin6_scope_id,
jsgf855d93d2003-10-13 22:26:55 +0000397 sizeof (uint32_t));
sewardj32102152002-05-04 10:28:17 +0000398# endif
sewardjc483e8f2002-05-03 21:01:35 +0000399 break;
400
401 default:
402 VG_(sprintf) ( outmsg, description, "" );
njn72718642003-07-24 08:45:32 +0000403 SYSCALL_TRACK( pre_mem_read, tid, outmsg, (UInt) sa, salen );
sewardjc483e8f2002-05-03 21:01:35 +0000404 break;
405 }
406
njn25e49d8e72002-09-23 09:36:25 +0000407 VG_(arena_free) ( VG_AR_TRANSIENT, outmsg );
sewardjc483e8f2002-05-03 21:01:35 +0000408}
409
njn25e49d8e72002-09-23 09:36:25 +0000410/* Dereference a pointer to a UInt. */
njn72718642003-07-24 08:45:32 +0000411static UInt deref_UInt ( ThreadId tid, Addr a, Char* s )
njn25e49d8e72002-09-23 09:36:25 +0000412{
413 UInt* a_p = (UInt*)a;
njn72718642003-07-24 08:45:32 +0000414 SYSCALL_TRACK( pre_mem_read, tid, s, (Addr)a_p, sizeof(UInt) );
njn25e49d8e72002-09-23 09:36:25 +0000415 if (a_p == NULL)
416 return 0;
417 else
418 return *a_p;
419}
420
421/* Dereference a pointer to a pointer. */
njn72718642003-07-24 08:45:32 +0000422static Addr deref_Addr ( ThreadId tid, Addr a, Char* s )
njn25e49d8e72002-09-23 09:36:25 +0000423{
424 Addr* a_p = (Addr*)a;
njn72718642003-07-24 08:45:32 +0000425 SYSCALL_TRACK( pre_mem_read, tid, s, (Addr)a_p, sizeof(Addr) );
njn25e49d8e72002-09-23 09:36:25 +0000426 return *a_p;
427}
428
429static
njn72718642003-07-24 08:45:32 +0000430void buf_and_len_pre_check( ThreadId tid, Addr buf_p, Addr buflen_p,
njn25e49d8e72002-09-23 09:36:25 +0000431 Char* buf_s, Char* buflen_s )
432{
433 if (VG_(track_events).pre_mem_write) {
njn72718642003-07-24 08:45:32 +0000434 UInt buflen_in = deref_UInt( tid, buflen_p, buflen_s);
njn25e49d8e72002-09-23 09:36:25 +0000435 if (buflen_in > 0) {
436 VG_(track_events).pre_mem_write ( Vg_CoreSysCall,
jsgf855d93d2003-10-13 22:26:55 +0000437 tid, buf_s, buf_p, buflen_in );
njn25e49d8e72002-09-23 09:36:25 +0000438 }
439 }
440}
441
442static
njn72718642003-07-24 08:45:32 +0000443void buf_and_len_post_check( ThreadId tid, Int res,
njn25e49d8e72002-09-23 09:36:25 +0000444 Addr buf_p, Addr buflen_p, Char* s )
445{
446 if (!VG_(is_kerror)(res) && VG_(track_events).post_mem_write) {
njn72718642003-07-24 08:45:32 +0000447 UInt buflen_out = deref_UInt( tid, buflen_p, s);
njn25e49d8e72002-09-23 09:36:25 +0000448 if (buflen_out > 0 && buf_p != (Addr)NULL) {
449 VG_(track_events).post_mem_write ( buf_p, buflen_out );
450 }
451 }
452}
453
454/* ---------------------------------------------------------------------
455 Data seg end, for brk()
456 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000457
458/* Records the current end of the data segment so we can make sense of
njn25e49d8e72002-09-23 09:36:25 +0000459 calls to brk(). */
sewardja38e0922002-10-01 00:50:47 +0000460static
njn25e49d8e72002-09-23 09:36:25 +0000461Addr curr_dataseg_end;
sewardjde4a1d02002-03-22 01:27:54 +0000462
njn25e49d8e72002-09-23 09:36:25 +0000463void VG_(init_dataseg_end_for_brk) ( void )
464{
465 curr_dataseg_end = (Addr)VG_(brk)(0);
466 if (curr_dataseg_end == (Addr)(-1))
njne427a662002-10-02 11:08:25 +0000467 VG_(core_panic)("can't determine data-seg end for brk()");
njn25e49d8e72002-09-23 09:36:25 +0000468 if (0)
469 VG_(printf)("DS END is %p\n", (void*)curr_dataseg_end);
470}
sewardjde4a1d02002-03-22 01:27:54 +0000471
njn25e49d8e72002-09-23 09:36:25 +0000472/* ---------------------------------------------------------------------
jsgf855d93d2003-10-13 22:26:55 +0000473 Vet file descriptors for sanity
474 ------------------------------------------------------------------ */
475
476/* Return true if we're allowed to use or create this fd */
477static Bool fd_allowed(Int fd, const Char *syscall, ThreadId tid)
478{
479 if (fd < 0 || fd > VG_MAX_FD || fd == VG_(clo_logfile_fd)) {
480 VG_(message)(Vg_UserMsg, "Warning: bad use of file descriptor %d in syscall %s()",
481 fd, syscall);
482 if (fd == VG_(clo_logfile_fd))
483 VG_(message)(Vg_UserMsg, " Use --logfile-fd=<number> to select an alternative "
484 "logfile fd.");
485 if (VG_(clo_verbosity) > 1) {
486 ExeContext *ec = VG_(get_ExeContext)(tid);
487 VG_(pp_ExeContext)(ec);
488 }
489 return False;
490 }
491 return True;
492}
493
494
495/* ---------------------------------------------------------------------
njn25e49d8e72002-09-23 09:36:25 +0000496 The Main Entertainment ...
497 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000498
jsgf855d93d2003-10-13 22:26:55 +0000499
500#define PRE(x) \
501 static void before_##x(ThreadId tid, ThreadState *tst)
502#define POST(x) \
503 static void after_##x(ThreadId tid, ThreadState *tst)
504
505#define STR(x) #x
506#define PREALIAS(new, old) \
507 PRE(new) __attribute__((alias(STR(before_##old))))
508#define POSTALIAS(new, old) \
509 POST(new) __attribute__((alias(STR(after_##old))))
510
511#define SYSNO (tst->m_eax) /* in PRE(x) */
512#define res ((Int)tst->m_eax) /* in POST(x) */
513#define arg1 (tst->m_ebx)
514#define arg2 (tst->m_ecx)
515#define arg3 (tst->m_edx)
516#define arg4 (tst->m_esi)
517#define arg5 (tst->m_edi)
518#define arg6 (tst->m_ebp)
519
520PRE(exit_group)
521{
522 VG_(core_panic)("syscall exit_group() not caught by the scheduler?!");
523}
524
525PRE(exit)
526{
527 VG_(core_panic)("syscall exit() not caught by the scheduler?!");
528}
529
530PRE(clone)
531{
532 VG_(unimplemented)
533 ("clone(): not supported by Valgrind.\n "
534 "We do now support programs linked against\n "
535 "libpthread.so, though. Re-run with -v and ensure that\n "
536 "you are picking up Valgrind's implementation of libpthread.so.");
537}
538
539PRE(ptrace)
540{
541 /* long ptrace (enum __ptrace_request request, pid_t pid,
542 void *addr, void *data); ... sort of. */
543 /* Sigh ... the /usr/include/sys/user.h on R H 6.2 doesn't
544 define struct user_fpxregs_struct. On the basis that it
545 is defined as follows on my R H 7.2 (glibc-2.2.4) box,
546 I kludge it.
547
548 struct user_fpxregs_struct
549 {
550 unsigned short int cwd;
551 unsigned short int swd;
552 unsigned short int twd;
553 unsigned short int fop;
554 long int fip;
555 long int fcs;
556 long int foo;
557 long int fos;
558 long int mxcsr;
559 long int reserved;
560 long int st_space[32]; 8*16 bytes for each FP-reg = 128 bytes
561 long int xmm_space[32]; 8*16 bytes for each XMM-reg = 128 bytes
562 long int padding[56];
563 };
564 */
565 const Int sizeof_struct_user_fpxregs_struct
566 = sizeof(unsigned short) * (1 + 1 + 1 + 1)
567 + sizeof(long int) * (1 + 1 + 1 + 1 + 1 + 1 + 32 + 32 + 56);
568
569 MAYBE_PRINTF("ptrace ( %d, %d, %p, %p )\n", arg1,arg2,arg3,arg4);
570 switch (arg1) {
571 case 12: /* PTRACE_GETREGS */
572 SYSCALL_TRACK( pre_mem_write, tid, "ptrace(getregs)", arg4,
573 sizeof (struct user_regs_struct));
574 break;
575 case 14: /* PTRACE_GETFPREGS */
576 SYSCALL_TRACK( pre_mem_write, tid, "ptrace(getfpregs)", arg4,
577 sizeof (struct user_fpregs_struct));
578 break;
579 case 18: /* PTRACE_GETFPXREGS */
580 SYSCALL_TRACK( pre_mem_write, tid, "ptrace(getfpxregs)", arg4,
581 sizeof_struct_user_fpxregs_struct);
582 break;
583 case 1: case 2: case 3: /* PTRACE_PEEK{TEXT,DATA,USER} */
584 SYSCALL_TRACK( pre_mem_write, tid, "ptrace(peek)", arg4,
585 sizeof (long));
586 break;
587 case 13: /* PTRACE_SETREGS */
588 SYSCALL_TRACK( pre_mem_read, tid, "ptrace(setregs)", arg4,
589 sizeof (struct user_regs_struct));
590 break;
591 case 15: /* PTRACE_SETFPREGS */
592 SYSCALL_TRACK( pre_mem_read, tid, "ptrace(setfpregs)", arg4,
593 sizeof (struct user_fpregs_struct));
594 break;
595 case 19: /* PTRACE_SETFPXREGS */
596 SYSCALL_TRACK( pre_mem_read, tid, "ptrace(setfpxregs)", arg4,
597 sizeof_struct_user_fpxregs_struct);
598 break;
599 default:
600 break;
601 }
602}
603
604POST(ptrace)
605{
606 const Int sizeof_struct_user_fpxregs_struct
607 = sizeof(unsigned short) * (1 + 1 + 1 + 1)
608 + sizeof(long int) * (1 + 1 + 1 + 1 + 1 + 1 + 32 + 32 + 56);
609
610 switch (arg1) {
611 case 12: /* PTRACE_GETREGS */
612 VG_TRACK( post_mem_write, arg4,
613 sizeof (struct user_regs_struct));
614 break;
615 case 14: /* PTRACE_GETFPREGS */
616 VG_TRACK( post_mem_write, arg4,
617 sizeof (struct user_fpregs_struct));
618 break;
619 case 18: /* PTRACE_GETFPXREGS */
620 VG_TRACK( post_mem_write, arg4,
621 sizeof_struct_user_fpxregs_struct);
622 break;
623 case 1: case 2: case 3: /* PTRACE_PEEK{TEXT,DATA,USER} */
624 VG_TRACK( post_mem_write, arg4, sizeof (long));
625 break;
626 default:
627 break;
628 }
629}
630
631PRE(mount)
632{
633 MAYBE_PRINTF( "mount( %p, %p, %p )\n" ,arg1,arg2,arg3);
634 SYSCALL_TRACK( pre_mem_read_asciiz, tid,"mount(specialfile)",arg1);
635 SYSCALL_TRACK( pre_mem_read_asciiz, tid,"mount(dir)",arg2);
636 SYSCALL_TRACK( pre_mem_read_asciiz, tid,"mount(filesystemtype)",arg3);
637}
638
639PRE(umount)
640{
641 /* int umount(const char *path) */
642 MAYBE_PRINTF("umount( %p )\n", arg1);
643 SYSCALL_TRACK( pre_mem_read_asciiz, tid,"umount(path)",arg1);
644}
645
646PRE(modify_ldt)
647{
648 MAYBE_PRINTF("modify_ldt ( %d, %p, %d )\n", arg1,arg2,arg3);
649 if (arg1 == 0) {
650 /* read the LDT into ptr */
651 SYSCALL_TRACK( pre_mem_write, tid,
652 "modify_ldt(ptr)(func=0)", arg2, arg3 );
653 }
654 if (arg1 == 1 || arg1 == 0x11) {
655 /* write the LDT with the entry pointed at by ptr */
656 SYSCALL_TRACK( pre_mem_read, tid,
657 "modify_ldt(ptr)(func=1 or 0x11)", arg2,
658 sizeof(struct vki_modify_ldt_ldt_s) );
659 }
660 /* "do" the syscall ourselves; the kernel never sees it */
661 res = VG_(sys_modify_ldt)( tid, arg1, (void*)arg2, arg3 );
662
663 if (arg1 == 0 && !VG_(is_kerror)(res) && res > 0) {
664 VG_TRACK( post_mem_write, arg2, res );
665 }
666}
667
668PRE(setresgid)
669{
670 /* int setresgid(gid_t rgid, gid_t egid, gid_t sgid); */
671 MAYBE_PRINTF("setresgid ( %d, %d, %d )\n", arg1, arg2, arg3);
672}
673
674PRE(vhangup)
675{
676 MAYBE_PRINTF("vhangup()\n");
677}
678
679PRE(iopl)
680{
681 MAYBE_PRINTF("iopl ( %d )\n", arg1);
682}
683
684PRE(setxattr)
685{
686 MAYBE_PRINTF("setxattr ( %p, %p, %p, %d, %d )\n",
687 arg1, arg2, arg3, arg4, arg5);
688 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "setxattr(path)", arg1 );
689 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "setxattr(name)", arg2 );
690 SYSCALL_TRACK( pre_mem_read, tid, "setxattr(value)", arg3, arg4 );
691}
692
693PREALIAS(lsetxattr, setxattr);
694
695PRE(fsetxattr)
696{
697 /* int fsetxattr (int filedes, const char *name,
698 const void *value, size_t size, int flags); */
699 MAYBE_PRINTF("fsetxattr ( %d, %p, %p, %d, %d )\n",
700 arg1, arg2, arg3, arg4, arg5);
701 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "fsetxattr(name)", arg2 );
702 SYSCALL_TRACK( pre_mem_read, tid, "fsetxattr(value)", arg3, arg4 );
703}
704
705PRE(getxattr)
706{
707 MAYBE_PRINTF("getxattr ( %p, %p, %p, %d )\n",
708 arg1,arg2,arg3, arg4);
709 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "getxattr(path)", arg1 );
710 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "getxattr(name)", arg2 );
711 SYSCALL_TRACK( pre_mem_write, tid, "getxattr(value)", arg3, arg4 );
712}
713
714POST(getxattr)
715{
716 if (res > 0 && arg3 != (Addr)NULL) {
717 VG_TRACK( post_mem_write, arg3, res );
718 }
719}
720
721PREALIAS(lgetxattr, getxattr);
722POSTALIAS(lgetxattr, getxattr);
723
724PRE(fgetxattr)
725{
726 MAYBE_PRINTF("fgetxattr ( %d, %p, %p, %d )\n",
727 arg1, arg2, arg3, arg4);
728 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "fgetxattr(name)", arg2 );
729 SYSCALL_TRACK( pre_mem_write, tid, "fgetxattr(value)", arg3, arg4 );
730}
731
732POST(fgetxattr)
733{
734 if (res > 0 && arg3 != (Addr)NULL)
735 VG_TRACK( post_mem_write, arg3, res );
736}
737
738PRE(listxattr)
739{
740 MAYBE_PRINTF("listxattr ( %p, %p, %d )\n", arg1, arg2, arg3);
741 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "listxattr(path)", arg1 );
742 SYSCALL_TRACK( pre_mem_write, tid, "listxattr(list)", arg2, arg3 );
743}
744
745POST(listxattr)
746{
747 if (res > 0 && arg2 != (Addr)NULL)
748 VG_TRACK( post_mem_write, arg2, res );
749}
750
751PREALIAS(llistxattr, listxattr);
752POSTALIAS(llistxattr, listxattr);
753
754PRE(flistxattr)
755{
756 /* ssize_t flistxattr (int filedes, char *list, size_t size); */
757 MAYBE_PRINTF("flistxattr ( %d, %p, %d )\n", arg1, arg2, arg3);
758 SYSCALL_TRACK( pre_mem_write, tid, "listxattr(list)", arg2, arg3 );
759}
760
761POST(flistxattr)
762{
763 if (res > 0 && arg2 != (Addr)NULL)
764 VG_TRACK( post_mem_write, arg2, res );
765}
766
767PRE(removexattr)
768{
769 MAYBE_PRINTF("removexattr ( %p, %p )\n", arg1, arg2);
770 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "listxattr(path)", arg1 );
771 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "listxattr(name)", arg2 );
772}
773
774PREALIAS(lremovexattr, removexattr);
775
776PRE(fremovexattr)
777{
778 MAYBE_PRINTF("removexattr ( %d, %p )\n", arg1, arg2);
779 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "listxattr(name)", arg2 );
780}
781
782PRE(quotactl)
783{
784 MAYBE_PRINTF("quotactl (0x%x, %p, 0x%x, 0x%x )\n",
785 arg1,arg2,arg3, arg4);
786 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "quotactl(special)", arg2 );
787}
788
789PRE(lookup_dcookie)
790{
791 MAYBE_PRINTF("lookup_dcookie (0x%llx, %p, %d)\n",
792 arg1 | ((long long) arg2 << 32), arg3, arg4);
793 SYSCALL_TRACK( pre_mem_write, tid, "lookup_dcookie(buf)", arg3, arg4);
794}
795
796POST(lookup_dcookie)
797{
798 if (arg3 != (Addr)NULL)
799 VG_TRACK( post_mem_write, arg3, res);
800}
801
802PRE(truncate64)
803{
804 MAYBE_PRINTF("truncate64 ( %p, %lld )\n",
805 arg1, ((ULong)arg2) | (((ULong) arg3) << 32));
806 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "truncate64(path)", arg1 );
807}
808
809PRE(fdatasync)
810{
811 /* int fdatasync(int fd); */
812 MAYBE_PRINTF("fdatasync ( %d )\n", arg1);
813}
814
815PRE(msync)
816{
817 /* int msync(const void *start, size_t length, int flags); */
818 MAYBE_PRINTF("msync ( %p, %d, %d )\n", arg1,arg2,arg3);
819 SYSCALL_TRACK( pre_mem_read, tid, "msync(start)", arg1, arg2 );
820}
821
822struct getpmsg_strbuf {
823 int maxlen; /* no. of bytes in buffer */
824 int len; /* no. of bytes returned */
825 caddr_t buf; /* pointer to data */
826};
827
828PRE(getpmsg)
829{
830 /* LiS getpmsg from http://www.gcom.com/home/linux/lis/ */
831 /* int getpmsg(int fd, struct strbuf *ctrl, struct strbuf *data,
832 int *bandp, int *flagsp); */
833 struct getpmsg_strbuf *ctrl;
834 struct getpmsg_strbuf *data;
835 MAYBE_PRINTF("getpmsg ( %d, %p, %p, %p, %p )\n",
836 arg1,arg2,arg3,arg4,arg5);
837 ctrl = (struct getpmsg_strbuf *)arg2;
838 data = (struct getpmsg_strbuf *)arg3;
839 if (ctrl && ctrl->maxlen > 0)
840 SYSCALL_TRACK( pre_mem_write,tid, "getpmsg(ctrl)",
841 (UInt)ctrl->buf, ctrl->maxlen);
842 if (data && data->maxlen > 0)
843 SYSCALL_TRACK( pre_mem_write,tid, "getpmsg(data)",
844 (UInt)data->buf, data->maxlen);
845 if (arg4)
846 SYSCALL_TRACK( pre_mem_write,tid, "getpmsg(bandp)",
847 (UInt)arg4, sizeof(int));
848 if (arg5)
849 SYSCALL_TRACK( pre_mem_write,tid, "getpmsg(flagsp)",
850 (UInt)arg5, sizeof(int));
851}
852
853POST(getpmsg)
854{
855 struct getpmsg_strbuf *ctrl;
856 struct getpmsg_strbuf *data;
857
858 ctrl = (struct getpmsg_strbuf *)arg2;
859 data = (struct getpmsg_strbuf *)arg3;
860 if (res == 0 && ctrl && ctrl->len > 0) {
861 VG_TRACK( post_mem_write, (UInt)ctrl->buf, ctrl->len);
862 }
863 if (res == 0 && data && data->len > 0) {
864 VG_TRACK( post_mem_write, (UInt)data->buf, data->len);
865 }
866}
867
868PRE(putpmsg)
869{
870 /* LiS putpmsg from http://www.gcom.com/home/linux/lis/ */
871 /* int putpmsg(int fd, struct strbuf *ctrl, struct strbuf *data,
872 int band, int flags); */
873 struct strbuf {
874 int maxlen; /* no. of bytes in buffer */
875 int len; /* no. of bytes returned */
876 caddr_t buf; /* pointer to data */
877 };
878 struct strbuf *ctrl;
879 struct strbuf *data;
880 MAYBE_PRINTF("putpmsg ( %d, %p, %p, %d, %d )\n",
881 arg1,arg2,arg3,arg4,arg5);
882 ctrl = (struct strbuf *)arg2;
883 data = (struct strbuf *)arg3;
884 if (ctrl && ctrl->len > 0)
885 SYSCALL_TRACK( pre_mem_read,tid, "putpmsg(ctrl)",
886 (UInt)ctrl->buf, ctrl->len);
887 if (data && data->len > 0)
888 SYSCALL_TRACK( pre_mem_read,tid, "putpmsg(data)",
889 (UInt)data->buf, data->len);
890}
891
892PRE(getitimer)
893{
894 /* int getitimer(int which, struct itimerval *value); */
895 MAYBE_PRINTF("getitimer ( %d, %p )\n", arg1, arg2);
896 SYSCALL_TRACK( pre_mem_write, tid, "getitimer(timer)", arg2,
897 sizeof(struct itimerval) );
898}
899
900POST(getitimer)
901{
902 if (arg2 != (Addr)NULL) {
903 VG_TRACK( post_mem_write,arg2, sizeof(struct itimerval));
904 }
905}
906
907PRE(syslog)
908{
909 /* int syslog(int type, char *bufp, int len); */
910 MAYBE_PRINTF("syslog (%d, %p, %d)\n",arg1,arg2,arg3);
911 switch(arg1) {
912 case 2: case 3: case 4:
913 SYSCALL_TRACK( pre_mem_write, tid, "syslog(buf)", arg2, arg3);
914 break;
915 default:
916 break;
917 }
918}
919
920POST(syslog)
921{
922 switch (arg1) {
923 case 2: case 3: case 4:
924 VG_TRACK( post_mem_write, arg2, arg3 );
925 break;
926 default:
927 break;
928 }
929}
930
931PRE(personality)
932{
933 /* int personality(unsigned long persona); */
934 MAYBE_PRINTF("personality ( %d )\n", arg1);
935}
936
937PRE(chroot)
938{
939 /* int chroot(const char *path); */
940 MAYBE_PRINTF("chroot ( %p )\n", arg1);
941 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "chroot(path)", arg1 );
942}
943
944PRE(madvise)
945{
946 /* int madvise(void *start, size_t length, int advice ); */
947 MAYBE_PRINTF("madvise ( %p, %d, %d )\n", arg1,arg2,arg3);
948}
949
950PRE(mremap)
951{
952 /* void* mremap(void * old_address, size_t old_size,
953 size_t new_size, unsigned long flags); */
954 MAYBE_PRINTF("mremap ( %p, %d, %d, 0x%x )\n",
955 arg1, arg2, arg3, arg4);
956 SYSCALL_TRACK( pre_mem_write, tid, "mremap(old_address)", arg1, arg2 );
957}
958
959POST(mremap)
960{
961 mremap_segment( arg1, arg2, (Addr)res, arg3 );
962}
963
964PRE(nice)
965{
966 /* int nice(int inc); */
967 MAYBE_PRINTF("nice ( %d )\n", arg1);
968}
969
970PRE(setresgid32)
971{
972 /* int setresgid(gid_t rgid, gid_t egid, gid_t sgid); */
973 MAYBE_PRINTF("setresgid32 ( %d, %d, %d )\n", arg1, arg2, arg3);
974}
975
976PRE(setfsuid32)
977{
978 /* int setfsuid(uid_t fsuid); */
979 MAYBE_PRINTF("setfsuid ( %d )\n", arg1);
980}
981
982PRE(_sysctl)
983{
984 /* int _sysctl(struct __sysctl_args *args); */
985 MAYBE_PRINTF("_sysctl ( %p )\n", arg1 );
986 SYSCALL_TRACK( pre_mem_write, tid, "_sysctl(args)", arg1,
987 sizeof(struct __sysctl_args) );
988}
989
990POST(_sysctl)
991{
992 VG_TRACK( post_mem_write, arg1, sizeof(struct __sysctl_args) );
993
994}
995
996PRE(sched_getscheduler)
997{
998 /* int sched_getscheduler(pid_t pid); */
999 MAYBE_PRINTF("sched_getscheduler ( %d )\n", arg1);
1000}
1001
1002PRE(sched_setscheduler)
1003{
1004 /* int sched_setscheduler(pid_t pid, int policy,
1005 const struct sched_param *p); */
1006 MAYBE_PRINTF("sched_setscheduler ( %d, %d, %p )\n",arg1,arg2,arg3);
1007 if (arg3 != (UInt)NULL)
1008 SYSCALL_TRACK( pre_mem_read, tid,
1009 "sched_setscheduler(struct sched_param *p)",
1010 arg3, sizeof(struct sched_param));
1011}
1012
1013PRE(mlock)
1014{
1015 /* int mlock(const void * addr, size_t len) */
1016 MAYBE_PRINTF("mlock ( %p, %d )\n", arg1, arg2);
1017}
1018
1019PRE(munlock)
1020{
1021 /* int munlock(const void * addr, size_t len) */
1022 MAYBE_PRINTF("munlock ( %p, %d )\n", arg1, arg2);
1023}
1024
1025PRE(mlockall)
1026{
1027 /* int mlockall(int flags); */
1028 MAYBE_PRINTF("mlockall ( %x )\n", arg1);
1029}
1030
1031PRE(munlockall)
1032{
1033 /* int munlock(const void * addr, size_t len) */
1034 MAYBE_PRINTF("munlock ( %p, %d )\n", arg1, arg2);
1035}
1036
1037PRE(sched_get_priority_max)
1038{
1039 /* int sched_get_priority_max(int policy); */
1040 MAYBE_PRINTF("sched_get_priority_max ( %d )\n", arg1);
1041}
1042
1043PRE(sched_get_priority_min)
1044{
1045 /* int sched_get_priority_min(int policy); */
1046 MAYBE_PRINTF("sched_get_priority_min ( %d )\n", arg1);
1047}
1048
1049PRE(setpriority)
1050{
1051 /* int setpriority(int which, int who, int prio); */
1052 MAYBE_PRINTF("setpriority ( %d, %d, %d )\n", arg1, arg2, arg3);
1053}
1054
1055PRE(getpriority)
1056{
1057 /* int getpriority(int which, int who); */
1058 MAYBE_PRINTF("getpriority ( %d, %d )\n", arg1, arg2);
1059}
1060
1061PRE(setfsgid)
1062{
1063 /* int setfsgid(gid_t gid); */
1064 MAYBE_PRINTF("setfsgid ( %d )\n", arg1);
1065}
1066
1067PRE(setregid)
1068{
1069 /* int setregid(gid_t rgid, gid_t egid); */
1070 MAYBE_PRINTF("setregid ( %d, %d )\n", arg1, arg2);
1071}
1072
1073PRE(setresuid)
1074{
1075 /* int setresuid(uid_t ruid, uid_t euid, uid_t suid); */
1076 MAYBE_PRINTF("setresuid ( %d, %d, %d )\n", arg1, arg2, arg3);
1077}
1078
1079PRE(setfsuid)
1080{
1081 /* int setfsuid(uid_t uid); */
1082 MAYBE_PRINTF("setfsuid ( %d )\n", arg1);
1083}
1084
1085PRE(sendfile)
1086{
1087 /* ssize_t sendfile(int out_fd, int in_fd, off_t *offset,
1088 size_t count) */
1089 MAYBE_PRINTF("sendfile ( %d, %d, %p, %d )\n",arg1,arg2,arg3,arg4);
1090 if (arg3 != (UInt)NULL)
1091 SYSCALL_TRACK( pre_mem_write, tid, "sendfile(offset)",
1092 arg3, sizeof(off_t) );
1093}
1094
1095POST(sendfile)
1096{
1097 VG_TRACK( post_mem_write, arg3, sizeof( off_t ) );
1098}
1099
1100PRE(sendfile64)
1101{
1102 /* ssize_t sendfile64(int out_df, int in_fd, loff_t *offset,
1103 size_t count); */
1104 MAYBE_PRINTF("sendfile64 ( %d, %d, %p, %d )\n",arg1,arg2,arg3,arg4);
1105 if (arg3 != (UInt)NULL)
1106 SYSCALL_TRACK( pre_mem_write, tid, "sendfile64(offset)",
1107 arg3, sizeof(loff_t) );
1108}
1109
1110POST(sendfile64)
1111{
1112 if (arg3 != (UInt)NULL ) {
1113 VG_TRACK( post_mem_write, arg3, sizeof(loff_t) );
1114 }
1115}
1116
1117PRE(pwrite64)
1118{
1119 /* ssize_t pwrite (int fd, const void *buf, size_t nbytes,
1120 off_t offset); */
1121 MAYBE_PRINTF("pwrite64 ( %d, %p, %d, %d )\n", arg1, arg2, arg3, arg4);
1122 SYSCALL_TRACK( pre_mem_read, tid, "pwrite(buf)", arg2, arg3 );
1123}
1124
1125PRE(sync)
1126{
1127 /* int sync(); */
1128 MAYBE_PRINTF("sync ( )\n");
1129}
1130
1131PRE(fstatfs)
1132{
1133 /* int fstatfs(int fd, struct statfs *buf); */
1134 MAYBE_PRINTF("fstatfs ( %d, %p )\n",arg1,arg2);
1135 SYSCALL_TRACK( pre_mem_write, tid, "stat(buf)",
1136 arg2, sizeof(struct statfs) );
1137}
1138
1139POST(fstatfs)
1140{
1141 VG_TRACK( post_mem_write, arg2, sizeof(struct statfs) );
1142}
1143
1144PRE(getsid)
1145{
1146 /* pid_t getsid(pid_t pid); */
1147 MAYBE_PRINTF("getsid ( %d )\n", arg1);
1148}
1149
1150PRE(pread64)
1151{
1152 /* ssize_t pread64(int fd, void *buf, size_t count, off_t offset); */
1153 MAYBE_PRINTF("pread ( %d, %p, %d, %d ) ...\n",arg1,arg2,arg3,arg4);
1154 SYSCALL_TRACK( pre_mem_write, tid, "pread(buf)", arg2, arg3 );
1155}
1156
1157POST(pread64)
1158{
1159 MAYBE_PRINTF("SYSCALL[%d] pread ( %d, %p, %d, %d ) --> %d\n",
1160 VG_(getpid)(),
1161 arg1, arg2, arg3, arg4, res);
1162 if (res > 0) {
1163 VG_TRACK( post_mem_write, arg2, res );
1164 }
1165}
1166
1167PRE(mknod)
1168{
1169 /* int mknod(const char *pathname, mode_t mode, dev_t dev); */
1170 MAYBE_PRINTF("mknod ( %p, 0x%x, 0x%x )\n", arg1, arg2, arg3 );
1171 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "mknod(pathname)", arg1 );
1172}
1173
1174PRE(flock)
1175{
1176 /* int flock(int fd, int operation); */
1177 MAYBE_PRINTF("flock ( %d, %d )\n", arg1, arg2 );
1178}
1179
1180PRE(init_module)
1181{
1182 /* int init_module(const char *name, struct module *image); */
1183 MAYBE_PRINTF("init_module ( %p, %p )\n", arg1, arg2 );
1184 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "init_module(name)", arg1 );
1185 SYSCALL_TRACK( pre_mem_read, tid, "init_module(image)", arg2,
1186 VKI_SIZEOF_STRUCT_MODULE );
1187}
1188
1189PRE(ioperm)
1190{
1191 /* int ioperm(unsigned long from, unsigned long num, int turn_on); */
1192 MAYBE_PRINTF("ioperm ( %d, %d, %d )\n", arg1, arg2, arg3 );
1193}
1194
1195PRE(capget)
1196{
1197 /* int capget(cap_user_header_t header, cap_user_data_t data); */
1198 MAYBE_PRINTF("capget ( %p, %p )\n", arg1, arg2 );
1199 SYSCALL_TRACK( pre_mem_read, tid, "capget(header)", arg1,
1200 sizeof(vki_cap_user_header_t) );
1201 SYSCALL_TRACK( pre_mem_write, tid, "capget(data)", arg2,
1202 sizeof( vki_cap_user_data_t) );
1203}
1204
1205POST(capget)
1206{
1207 if (arg2 != (Addr)NULL)
1208 VG_TRACK( post_mem_write, arg2, sizeof( vki_cap_user_data_t) );
1209}
1210
1211PRE(capset)
1212{
1213 SYSCALL_TRACK( pre_mem_read, tid, "capset(header)",
1214 arg1, sizeof(vki_cap_user_header_t) );
1215 SYSCALL_TRACK( pre_mem_read, tid, "capset(data)",
1216 arg2, sizeof( vki_cap_user_data_t) );
1217}
1218
1219PRE(execve)
1220{
1221 /* int execve (const char *filename,
1222 char *const argv [],
1223 char *const envp[]); */
1224 MAYBE_PRINTF("execve ( %p(%s), %p, %p ) --- NOT CHECKED\n",
1225 arg1, arg1, arg2, arg3);
fitzhardingee1c06d82003-10-30 07:21:44 +00001226
1227 /* Erk. If the exec fails, then the following will have made a
1228 mess of things which makes it hard for us to continue. The
1229 right thing to do is piece everything together again in
1230 POST(execve), but that's hard work. Instead, we make an effort
1231 to check that the execve will work before actually calling
1232 exec. */
1233 {
1234 struct vki_stat st;
1235 Int ret = VG_(stat)((Char *)arg1, &st);
1236
1237 if (ret < 0) {
1238 res = ret;
1239 return;
1240 }
1241 /* just look for any X bit set
1242 XXX do proper permissions check?
1243 */
1244 if ((st.st_mode & 0111) == 0) {
1245 res = -VKI_EACCES;
1246 return;
1247 }
1248 }
1249
1250 /* Resistance is futile. Nuke all other threads. POSIX mandates
1251 this. (Really, nuke them all, since the new process will make
1252 its own new thread.) */
1253 VG_(nuke_all_threads_except)( VG_INVALID_THREADID );
1254
jsgf855d93d2003-10-13 22:26:55 +00001255 /* Make any binding for LD_PRELOAD disappear, so that child
1256 processes don't get traced into. */
1257 if (!VG_(clo_trace_children)) {
1258 Int i;
1259 Char** envp = (Char**)arg3;
1260 Char* ld_preload_str = NULL;
1261 Char* ld_library_path_str = NULL;
1262 for (i = 0; envp[i] != NULL; i++) {
1263 if (VG_(strncmp)(envp[i], "LD_PRELOAD=", 11) == 0)
1264 ld_preload_str = &envp[i][11];
1265 if (VG_(strncmp)(envp[i], "LD_LIBRARY_PATH=", 16) == 0)
1266 ld_library_path_str = &envp[i][16];
1267 }
1268 VG_(mash_LD_PRELOAD_and_LD_LIBRARY_PATH)(
1269 ld_preload_str, ld_library_path_str );
1270 }
jsgf855d93d2003-10-13 22:26:55 +00001271
fitzhardingee1c06d82003-10-30 07:21:44 +00001272 res = VG_(do_syscall)(__NR_execve, arg1, arg2, arg3);
1273
1274 /* If we got here, then the execve failed. We've already made too much of a mess
1275 of ourselves to continue, so we have to abort. */
1276 VG_(message)(Vg_UserMsg, "execve(%p \"%s\", %p, %p) failed, errno %d",
1277 arg1, arg1, arg2, arg3, -res);
1278 VG_(core_panic)("EXEC FAILED: I can't recover from execve() failing, so I'm dying.\n"
1279 "Add more stringent tests in PRE(execve), or work out how to recover.");
jsgf855d93d2003-10-13 22:26:55 +00001280}
1281
1282PRE(access)
1283{
1284 /* int access(const char *pathname, int mode); */
1285 MAYBE_PRINTF("access ( %p, %d )\n", arg1,arg2);
1286 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "access(pathname)", arg1 );
1287}
1288
1289PRE(alarm)
1290{
1291 /* unsigned int alarm(unsigned int seconds); */
1292 MAYBE_PRINTF("alarm ( %d )\n", arg1);
1293}
1294
1295PRE(brk)
1296{
1297 /* libc says: int brk(void *end_data_segment);
1298 kernel says: void* brk(void* end_data_segment); (more or less)
1299
1300 libc returns 0 on success, and -1 (and sets errno) on failure.
1301 Nb: if you ask to shrink the dataseg end below what it
1302 currently is, that always succeeds, even if the dataseg end
1303 doesn't actually change (eg. brk(0)). Unless it seg faults.
1304
1305 Kernel returns the new dataseg end. If the brk() failed, this
1306 will be unchanged from the old one. That's why calling (kernel)
1307 brk(0) gives the current dataseg end (libc brk() just returns
1308 zero in that case).
1309
1310 Both will seg fault if you shrink it back into a text segment.
1311 */
1312 MAYBE_PRINTF("brk ( %p ) --> ",arg1);
1313}
1314
1315POST(brk)
1316{
1317 MAYBE_PRINTF("0x%x\n", res);
1318
1319 if (res == arg1) {
1320 /* brk() succeeded */
1321 if (res < curr_dataseg_end) {
1322 /* successfully shrunk the data segment. */
1323 VG_TRACK( die_mem_brk, (Addr)arg1,
1324 curr_dataseg_end-arg1 );
1325 } else
1326 if (res > curr_dataseg_end && res != 0) {
1327 /* successfully grew the data segment */
1328 VG_TRACK( new_mem_brk, curr_dataseg_end,
1329 arg1-curr_dataseg_end );
1330 }
1331 curr_dataseg_end = res;
1332 } else {
1333 /* brk() failed */
1334 vg_assert(curr_dataseg_end == res);
1335 }
1336}
1337
1338PRE(chdir)
1339{
1340 /* int chdir(const char *path); */
1341 MAYBE_PRINTF("chdir ( %p )\n", arg1);
1342 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "chdir(path)", arg1 );
1343}
1344
1345PRE(chmod)
1346{
1347 /* int chmod(const char *path, mode_t mode); */
1348 MAYBE_PRINTF("chmod ( %p, %d )\n", arg1,arg2);
1349 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "chmod(path)", arg1 );
1350}
1351
1352PRE(chown)
1353{
1354 /* int chown(const char *path, uid_t owner, gid_t group); */
1355 MAYBE_PRINTF("chown ( %p, 0x%x, 0x%x )\n", arg1,arg2,arg3);
1356 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "chown(path)", arg1 );
1357}
1358
1359PREALIAS(chown32, chown);
1360PREALIAS(lchown32, chown);
1361
1362PRE(close)
1363{
1364 /* int close(int fd); */
1365 MAYBE_PRINTF("close ( %d )\n",arg1);
1366 /* Detect and negate attempts by the client to close Valgrind's
1367 logfile fd ... */
1368 if (!fd_allowed(arg1, "close", tid))
1369 res = -VKI_EBADF;
1370}
1371
1372
1373PRE(dup)
1374{
1375 /* int dup(int oldfd); */
1376 MAYBE_PRINTF("dup ( %d ) --> ", arg1);
1377}
1378
1379POST(dup)
1380{
1381 MAYBE_PRINTF("%d\n", res);
1382 if (!fd_allowed(res, "dup", tid)) {
1383 VG_(close)(res);
1384 res = -VKI_EMFILE;
1385 }
1386}
1387
1388PRE(dup2)
1389{
1390 /* int dup2(int oldfd, int newfd); */
1391 MAYBE_PRINTF("dup2 ( %d, %d ) ...\n", arg1,arg2);
1392 if (!fd_allowed(arg2, "dup2", tid))
1393 res = -VKI_EBADF;
1394}
1395
1396POST(dup2)
1397{
1398 MAYBE_PRINTF("SYSCALL[%d] dup2 ( %d, %d ) = %d\n",
1399 VG_(getpid)(),
1400 arg1, arg2, res);
1401}
1402
1403PRE(fcntl)
1404{
1405 /* int fcntl(int fd, int cmd, int arg); */
1406 MAYBE_PRINTF("fcntl ( %d, %d, %d )\n",arg1,arg2,arg3);
1407}
1408
1409PRE(fchdir)
1410{
1411 /* int fchdir(int fd); */
1412 MAYBE_PRINTF("fchdir ( %d )\n", arg1);
1413}
1414
1415PRE(fchown)
1416{
1417 /* int fchown(int filedes, uid_t owner, gid_t group); */
1418 MAYBE_PRINTF("fchown ( %d, %d, %d )\n", arg1,arg2,arg3);
1419}
1420
1421PREALIAS(fchown32, fchown);
1422
1423PRE(fchmod)
1424{
1425 /* int fchmod(int fildes, mode_t mode); */
1426 MAYBE_PRINTF("fchmod ( %d, %d )\n", arg1,arg2);
1427}
1428
1429PRE(fcntl64)
1430{
1431 /* I don't know what the prototype for this is supposed to be. */
1432 /* ??? int fcntl(int fd, int cmd); */
1433 MAYBE_PRINTF("fcntl64 (?!) ( %d, %d )\n", arg1,arg2);
1434}
1435
1436PRE(fstat)
1437{
1438 /* int fstat(int filedes, struct stat *buf); */
1439 MAYBE_PRINTF("fstat ( %d, %p )\n",arg1,arg2);
1440 SYSCALL_TRACK( pre_mem_write, tid, "fstat", arg2, sizeof(struct stat) );
1441}
1442
1443POST(fstat)
1444{
1445 VG_TRACK( post_mem_write, arg2, sizeof(struct stat) );
1446}
1447
1448static vki_ksigset_t fork_saved_mask;
1449
1450PRE(fork)
1451{
1452 vki_ksigset_t mask;
1453
1454 vg_assert(VG_(gettid)() == VG_(main_pid));
1455
1456 /* Block all signals during fork, so that we can fix things up in
1457 the child without being interrupted. */
1458 VG_(ksigfillset)(&mask);
1459 VG_(ksigprocmask)(VKI_SIG_SETMASK, &mask, &fork_saved_mask);
1460
1461 /* pid_t fork(void); */
1462 MAYBE_PRINTF("fork ()\n");
1463
1464 do_atfork_pre(tid);
1465}
1466
1467POST(fork)
1468{
1469 if (res == 0) {
1470 do_atfork_child(tid);
1471
1472 /* I am the child. Nuke all other threads which I might
1473 have inherited from my parent. POSIX mandates this. */
1474 VG_(nuke_all_threads_except)( tid );
1475
1476 /* XXX TODO: tid 1 is special, and is presumed to be present.
1477 We should move this TID to 1 in the child. */
1478
1479 /* restore signal mask */
1480 VG_(ksigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
1481 } else {
1482 MAYBE_PRINTF(" fork: process %d created child %d\n", VG_(main_pid), res);
1483
1484 do_atfork_parent(tid);
1485
1486 /* restore signal mask */
1487 VG_(ksigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
1488 }
1489}
1490
1491PRE(fsync)
1492{
1493 /* int fsync(int fd); */
1494 MAYBE_PRINTF("fsync ( %d )\n", arg1);
1495}
1496
1497PRE(ftruncate)
1498{
1499 /* int ftruncate(int fd, size_t length); */
1500 MAYBE_PRINTF("ftruncate ( %d, %d )\n", arg1,arg2);
1501}
1502
1503PRE(ftruncate64)
1504{
1505 /* int ftruncate64(int fd, off64_t length); */
1506 MAYBE_PRINTF("ftruncate64 ( %d, %lld )\n",
1507 arg1,arg2|((long long) arg3 << 32));
1508}
1509
1510PRE(getdents)
1511{
1512 /* int getdents(unsigned int fd, struct dirent *dirp,
1513 unsigned int count); */
1514 MAYBE_PRINTF("getdents ( %d, %p, %d )\n",arg1,arg2,arg3);
1515 SYSCALL_TRACK( pre_mem_write, tid, "getdents(dirp)", arg2, arg3 );
1516}
1517
1518POST(getdents)
1519{
1520 if (res > 0)
1521 VG_TRACK( post_mem_write, arg2, res );
1522}
1523
1524PRE(getdents64)
1525{
1526 /* int getdents(unsigned int fd, struct dirent64 *dirp,
1527 unsigned int count); */
1528 MAYBE_PRINTF("getdents64 ( %d, %p, %d )\n",arg1,arg2,arg3);
1529 SYSCALL_TRACK( pre_mem_write, tid, "getdents64(dirp)", arg2, arg3 );
1530}
1531
1532POST(getdents64)
1533{
1534 if (res > 0)
1535 VG_TRACK( post_mem_write, arg2, res );
1536}
1537
1538PRE(getgroups)
1539{
1540 /* int getgroups(int size, gid_t list[]); */
1541 MAYBE_PRINTF("getgroups ( %d, %p )\n", arg1, arg2);
1542 if (arg1 > 0)
1543 SYSCALL_TRACK( pre_mem_write, tid, "getgroups(list)", arg2,
1544 arg1 * sizeof(gid_t) );
1545}
1546
1547POST(getgroups)
1548{
1549 if (arg1 > 0 && res > 0)
1550 VG_TRACK( post_mem_write, arg2, res * sizeof(gid_t) );
1551}
1552
1553PREALIAS(getgroups32, getgroups);
1554POSTALIAS(getgroups32, getgroups);
1555
1556PRE(getcwd)
1557{
1558 /* char *getcwd(char *buf, size_t size); (but see comment below) */
1559 MAYBE_PRINTF("getcwd ( %p, %d )\n",arg1,arg2);
1560 SYSCALL_TRACK( pre_mem_write, tid, "getcwd(buf)", arg1, arg2 );
1561}
1562
1563POST(getcwd)
1564{
1565 if (res != (Addr)NULL)
1566 VG_TRACK( post_mem_write, arg1, res );
1567}
1568
1569PRE(geteuid)
1570{
1571 /* uid_t geteuid(void); */
1572 MAYBE_PRINTF("geteuid ( )\n");
1573}
1574
1575PRE(geteuid32)
1576{
1577 /* ?? uid_t geteuid32(void); */
1578 MAYBE_PRINTF("geteuid32(?) ( )\n");
1579}
1580
1581PRE(getegid)
1582{
1583 /* gid_t getegid(void); */
1584 MAYBE_PRINTF("getegid ()\n");
1585}
1586
1587PRE(getegid32)
1588{
1589 /* gid_t getegid32(void); */
1590 MAYBE_PRINTF("getegid32 ()\n");
1591}
1592
1593PRE(getgid)
1594{
1595 /* gid_t getgid(void); */
1596 MAYBE_PRINTF("getgid ()\n");
1597}
1598
1599PRE(getgid32)
1600{
1601 /* gid_t getgid32(void); */
1602 MAYBE_PRINTF("getgid32 ()\n");
1603}
1604
1605PRE(getpid)
1606{
1607 /* pid_t getpid(void); */
1608 MAYBE_PRINTF("getpid ()\n");
1609}
1610
1611PRE(getpgid)
1612{
1613 /* pid_t getpgid(pid_t pid); */
1614 MAYBE_PRINTF("getpgid ( %d )\n", arg1);
1615}
1616
1617PRE(getpgrp)
1618{
1619 /* pid_t getpgrp(void); */
1620 MAYBE_PRINTF("getpgrp ()\n");
1621}
1622
1623PRE(getppid)
1624{
1625 /* pid_t getppid(void); */
1626 MAYBE_PRINTF("getppid ()\n");
1627}
1628
1629PRE(getresgid)
1630{
1631 /* int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); */
1632 MAYBE_PRINTF("getresgid ( %p, %p, %p )\n", arg1,arg2,arg3);
1633 SYSCALL_TRACK( pre_mem_write, tid, "getresgid(rgid)",
1634 arg1, sizeof(gid_t) );
1635 SYSCALL_TRACK( pre_mem_write, tid, "getresgid(egid)",
1636 arg2, sizeof(gid_t) );
1637 SYSCALL_TRACK( pre_mem_write, tid, "getresgid(sgid)",
1638 arg3, sizeof(gid_t) );
1639}
1640
1641POST(getresgid)
1642{
1643 if (res == 0) {
1644 VG_TRACK( post_mem_write, arg1, sizeof(gid_t) );
1645 VG_TRACK( post_mem_write, arg2, sizeof(gid_t) );
1646 VG_TRACK( post_mem_write, arg3, sizeof(gid_t) );
1647 }
1648}
1649
1650PRE(getresgid32)
1651{
1652 /* int getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid); */
1653 MAYBE_PRINTF("getresgid32 ( %p, %p, %p )\n", arg1,arg2,arg3);
1654 SYSCALL_TRACK( pre_mem_write, tid, "getresgid32(rgid)",
1655 arg1, sizeof(gid_t) );
1656 SYSCALL_TRACK( pre_mem_write, tid, "getresgid32(egid)",
1657 arg2, sizeof(gid_t) );
1658 SYSCALL_TRACK( pre_mem_write, tid, "getresgid32(sgid)",
1659 arg3, sizeof(gid_t) );
1660}
1661
1662POST(getresgid32)
1663{
1664 if (res == 0) {
1665 VG_TRACK( post_mem_write, arg1, sizeof(gid_t) );
1666 VG_TRACK( post_mem_write, arg2, sizeof(gid_t) );
1667 VG_TRACK( post_mem_write, arg3, sizeof(gid_t) );
1668 }
1669}
1670
1671PRE(getresuid)
1672{
1673 /* int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); */
1674 MAYBE_PRINTF("getresuid ( %p, %p, %p )\n", arg1,arg2,arg3);
1675 SYSCALL_TRACK( pre_mem_write, tid, "getresuid(ruid)",
1676 arg1, sizeof(uid_t) );
1677 SYSCALL_TRACK( pre_mem_write, tid, "getresuid(euid)",
1678 arg2, sizeof(uid_t) );
1679 SYSCALL_TRACK( pre_mem_write, tid, "getresuid(suid)",
1680 arg3, sizeof(uid_t) );
1681}
1682
1683POST(getresuid)
1684{
1685 if (res == 0) {
1686 VG_TRACK( post_mem_write, arg1, sizeof(uid_t) );
1687 VG_TRACK( post_mem_write, arg2, sizeof(uid_t) );
1688 VG_TRACK( post_mem_write, arg3, sizeof(uid_t) );
1689 }
1690}
1691
1692PRE(getresuid32)
1693{
1694 /* int getresuid(uid_t *ruid, uid_t *euid, uid_t *suid); */
1695 MAYBE_PRINTF("getresuid32 ( %p, %p, %p )\n", arg1,arg2,arg3);
1696 SYSCALL_TRACK( pre_mem_write, tid, "getresuid32(ruid)",
1697 arg1, sizeof(uid_t) );
1698 SYSCALL_TRACK( pre_mem_write, tid, "getresuid32(euid)",
1699 arg2, sizeof(uid_t) );
1700 SYSCALL_TRACK( pre_mem_write, tid, "getresuid32(suid)",
1701 arg3, sizeof(uid_t) );
1702}
1703
1704POST(getresuid32)
1705{
1706 if (res == 0) {
1707 VG_TRACK( post_mem_write, arg1, sizeof(uid_t) );
1708 VG_TRACK( post_mem_write, arg2, sizeof(uid_t) );
1709 VG_TRACK( post_mem_write, arg3, sizeof(uid_t) );
1710 }
1711}
1712
1713PRE(getrlimit)
1714{
1715 /* int getrlimit (int resource, struct rlimit *rlim); */
1716 MAYBE_PRINTF("getrlimit ( %d, %p )\n", arg1,arg2);
1717 SYSCALL_TRACK( pre_mem_write, tid, "getrlimit(rlim)", arg2,
1718 sizeof(struct rlimit) );
1719}
1720
1721POST(getrlimit)
1722{
1723 if (res == 0)
1724 VG_TRACK( post_mem_write, arg2, sizeof(struct rlimit) );
1725}
1726
1727PREALIAS(ugetrlimit, getrlimit);
1728POSTALIAS(ugetrlimit, getrlimit);
1729
1730PRE(getrusage)
1731{
1732 /* int getrusage (int who, struct rusage *usage); */
1733 MAYBE_PRINTF("getrusage ( %d, %p )\n", arg1,arg2);
1734 SYSCALL_TRACK( pre_mem_write, tid, "getrusage(usage)", arg2,
1735 sizeof(struct rusage) );
1736}
1737
1738POST(getrusage)
1739{
1740 if (res == 0)
1741 VG_TRACK( post_mem_write,arg2, sizeof(struct rusage) );
1742}
1743
1744PRE(gettimeofday)
1745{
1746 /* int gettimeofday(struct timeval *tv, struct timezone *tz); */
1747 MAYBE_PRINTF("gettimeofday ( %p, %p )\n",arg1,arg2);
1748 SYSCALL_TRACK( pre_mem_write, tid, "gettimeofday(tv)", arg1,
1749 sizeof(struct timeval) );
1750 if (arg2 != 0)
1751 SYSCALL_TRACK( pre_mem_write, tid, "gettimeofday(tz)", arg2,
1752 sizeof(struct timezone) );
1753}
1754
1755POST(gettimeofday)
1756{
1757 if (res == 0) {
1758 VG_TRACK( post_mem_write, arg1, sizeof(struct timeval) );
1759 if (arg2 != 0)
1760 VG_TRACK( post_mem_write, arg2, sizeof(struct timezone) );
1761 }
1762}
1763
1764PRE(getuid)
1765{
1766 /* uid_t getuid(void); */
1767 MAYBE_PRINTF("getuid ( )\n");
1768}
1769
1770PRE(getuid32)
1771{
1772 /* ???uid_t getuid32(void); */
1773 MAYBE_PRINTF("getuid32 ( )\n");
1774}
1775
1776PRE(ipc)
1777{
1778 MAYBE_PRINTF("ipc ( %d, %d, %d, %d, %p, %d )\n",
1779 arg1,arg2,arg3,arg4,arg5,arg6);
1780 switch (arg1 /* call */) {
1781 case 1: /* IPCOP_semop */
1782 SYSCALL_TRACK( pre_mem_read, tid, "semop(sops)", arg5,
1783 arg3 * sizeof(struct sembuf) );
1784 break;
1785 case 2: /* IPCOP_semget */
1786 case 3: /* IPCOP_semctl */
1787 break;
1788 case 11: /* IPCOP_msgsnd */
1789 {
1790 struct msgbuf *msgp = (struct msgbuf *)arg5;
1791 Int msgsz = arg3;
1792
1793 SYSCALL_TRACK( pre_mem_read, tid, "msgsnd(msgp->mtype)",
1794 (UInt)&msgp->mtype, sizeof(msgp->mtype) );
1795 SYSCALL_TRACK( pre_mem_read, tid, "msgsnd(msgp->mtext)",
1796 (UInt)msgp->mtext, msgsz );
1797 break;
1798 }
1799 case 12: /* IPCOP_msgrcv */
1800 {
1801 struct msgbuf *msgp;
1802 Int msgsz = arg3;
1803
1804 msgp = (struct msgbuf *)deref_Addr( tid,
1805 (Addr) (&((struct ipc_kludge *)arg5)->msgp),
1806 "msgrcv(msgp)" );
1807
1808 SYSCALL_TRACK( pre_mem_write, tid, "msgrcv(msgp->mtype)",
1809 (UInt)&msgp->mtype, sizeof(msgp->mtype) );
1810 SYSCALL_TRACK( pre_mem_write, tid, "msgrcv(msgp->mtext)",
1811 (UInt)msgp->mtext, msgsz );
1812 break;
1813 }
1814 case 13: /* IPCOP_msgget */
1815 break;
1816 case 14: /* IPCOP_msgctl */
1817 {
1818 switch (arg3 /* cmd */) {
1819 case IPC_STAT:
1820 SYSCALL_TRACK( pre_mem_write, tid, "msgctl(buf)", arg5,
1821 sizeof(struct msqid_ds) );
1822 break;
1823 case IPC_SET:
1824 SYSCALL_TRACK( pre_mem_read, tid, "msgctl(buf)", arg5,
1825 sizeof(struct msqid_ds) );
1826 break;
1827# if defined(IPC_64)
1828 case IPC_STAT|IPC_64:
1829 SYSCALL_TRACK( pre_mem_write, tid, "msgctl(buf)", arg5,
1830 sizeof(struct msqid64_ds) );
1831 break;
1832# endif
1833# if defined(IPC_64)
1834 case IPC_SET|IPC_64:
1835 SYSCALL_TRACK( pre_mem_read, tid, "msgctl(buf)", arg5,
1836 sizeof(struct msqid64_ds) );
1837 break;
1838# endif
1839 default:
1840 break;
1841 }
1842 break;
1843 }
1844 case 21: /* IPCOP_shmat */
1845 {
1846 break;
1847 }
1848 case 22: /* IPCOP_shmdt */
1849 break;
1850 case 23: /* IPCOP_shmget */
1851 break;
1852 case 24: /* IPCOP_shmctl */
1853 /* Subject: shmctl: The True Story
1854 Date: Thu, 9 May 2002 18:07:23 +0100 (BST)
1855 From: Reuben Thomas <rrt@mupsych.org>
1856 To: Julian Seward <jseward@acm.org>
1857
1858 1. As you suggested, the syscall subop is in arg1.
1859
1860 2. There are a couple more twists, so the arg order
1861 is actually:
1862
1863 arg1 syscall subop
1864 arg2 file desc
1865 arg3 shm operation code (can have IPC_64 set)
1866 arg4 0 ??? is arg3-arg4 a 64-bit quantity when IPC_64
1867 is defined?
1868 arg5 pointer to buffer
1869
1870 3. With this in mind, I've amended the case as below:
1871 */
1872 {
1873 UInt cmd = arg3;
1874 Bool out_arg = False;
1875 if ( arg5 ) {
1876# if defined(IPC_64)
1877 cmd = cmd & (~IPC_64);
1878# endif
1879 out_arg = cmd == SHM_STAT || cmd == IPC_STAT;
1880 if ( out_arg )
1881 SYSCALL_TRACK( pre_mem_write, tid,
1882 "shmctl(SHM_STAT or IPC_STAT,buf)",
1883 arg5, sizeof(struct shmid_ds) );
1884 else
1885 SYSCALL_TRACK( pre_mem_read, tid,
1886 "shmctl(SHM_XXXX,buf)",
1887 arg5, sizeof(struct shmid_ds) );
1888 }
1889 }
1890 break;
1891 default:
1892 VG_(message)(Vg_DebugMsg,
1893 "FATAL: unhandled syscall(ipc) %d",
1894 arg1 );
1895 VG_(core_panic)("... bye!\n");
1896 break; /*NOTREACHED*/
1897 }
1898}
1899
1900POST(ipc)
1901{
1902 switch (arg1 /* call */) {
1903 case 1: /* IPCOP_semop */
1904 break;
1905 case 2: /* IPCOP_semget */
1906 case 3: /* IPCOP_semctl */
1907 break;
1908 case 11: /* IPCOP_msgsnd */
1909 break;
1910 case 12: /* IPCOP_msgrcv */
1911 {
1912 struct msgbuf *msgp;
1913
1914 msgp = (struct msgbuf *)deref_Addr( tid,
1915 (Addr) (&((struct ipc_kludge *)arg5)->msgp),
1916 "msgrcv(msgp)" );
1917 if ( res > 0 ) {
1918 VG_TRACK( post_mem_write, (UInt)&msgp->mtype,
1919 sizeof(msgp->mtype) );
1920 VG_TRACK( post_mem_write, (UInt)msgp->mtext, res );
1921 }
1922 break;
1923 }
1924 case 13: /* IPCOP_msgget */
1925 break;
1926 case 14: /* IPCOP_msgctl */
1927 {
1928 switch (arg3 /* cmd */) {
1929 case IPC_STAT:
1930 if ( res > 0 ) {
1931 VG_TRACK( post_mem_write, arg5,
1932 sizeof(struct msqid_ds) );
1933 }
1934 break;
1935 case IPC_SET:
1936 break;
1937# if defined(IPC_64)
1938 case IPC_STAT|IPC_64:
1939 if ( res > 0 ) {
1940 VG_TRACK( post_mem_write, arg5,
1941 sizeof(struct msqid64_ds) );
1942 }
1943 break;
1944# endif
1945# if defined(IPC_64)
1946 case IPC_SET|IPC_64:
1947 break;
1948# endif
1949 default:
1950 break;
1951 }
1952 break;
1953 }
1954 case 21: /* IPCOP_shmat */
1955 {
1956 Int shmid = arg2;
1957 /*Int shmflag = arg3;*/
1958 Addr addr;
1959
1960
1961 /* force readability. before the syscall it is
1962 * indeed uninitialized, as can be seen in
1963 * glibc/sysdeps/unix/sysv/linux/shmat.c */
1964 VG_TRACK( post_mem_write, arg4, sizeof( ULong ) );
1965
1966 addr = deref_Addr ( tid, arg4, "shmat(addr)" );
1967 if ( addr > 0 ) {
1968 UInt segmentSize = get_shm_size ( shmid );
1969 if ( segmentSize > 0 ) {
1970 /* we don't distinguish whether it's read-only or
1971 * read-write -- it doesn't matter really. */
1972 VG_TRACK( new_mem_mmap, addr, segmentSize,
1973 True, True, False );
1974 }
1975 }
1976 break;
1977 }
1978 case 22: /* IPCOP_shmdt */
1979 /* ### FIXME: this should call make_noaccess on the
1980 * area passed to shmdt. But there's no way to
1981 * figure out the size of the shared memory segment
1982 * just from the address... Maybe we want to keep a
1983 * copy of the exiting mappings inside valgrind? */
1984 break;
1985 case 23: /* IPCOP_shmget */
1986 break;
1987 case 24: /* IPCOP_shmctl */
1988 /* Subject: shmctl: The True Story
1989 Date: Thu, 9 May 2002 18:07:23 +0100 (BST)
1990 From: Reuben Thomas <rrt@mupsych.org>
1991 To: Julian Seward <jseward@acm.org>
1992
1993 1. As you suggested, the syscall subop is in arg1.
1994
1995 2. There are a couple more twists, so the arg order
1996 is actually:
1997
1998 arg1 syscall subop
1999 arg2 file desc
2000 arg3 shm operation code (can have IPC_64 set)
2001 arg4 0 ??? is arg3-arg4 a 64-bit quantity when IPC_64
2002 is defined?
2003 arg5 pointer to buffer
2004
2005 3. With this in mind, I've amended the case as below:
2006 */
2007 {
2008 UInt cmd = arg3;
2009 Bool out_arg = False;
2010 if ( arg5 ) {
2011# if defined(IPC_64)
2012 cmd = cmd & (~IPC_64);
2013# endif
2014 out_arg = cmd == SHM_STAT || cmd == IPC_STAT;
2015 }
2016 if ( arg5 && res == 0 && out_arg )
2017 VG_TRACK( post_mem_write, arg5,
2018 sizeof(struct shmid_ds) );
2019 }
2020 break;
2021 default:
2022 VG_(message)(Vg_DebugMsg,
2023 "FATAL: unhandled syscall(ipc) %d",
2024 arg1 );
2025 VG_(core_panic)("... bye!\n");
2026 break; /*NOTREACHED*/
2027 }
2028}
2029
2030PRE(ioctl)
2031{
2032 /* int ioctl(int d, int request, ...)
2033 [The "third" argument is traditionally char *argp,
2034 and will be so named for this discussion.]
2035 */
2036 /*
2037 VG_(message)(
2038 Vg_DebugMsg,
2039 "is an IOCTL, request = 0x%x, d = %d, argp = 0x%x",
2040 arg2,arg1,arg3);
2041 */
2042 MAYBE_PRINTF("ioctl ( %d, 0x%x, %p )\n",arg1,arg2,arg3);
2043 switch (arg2 /* request */) {
2044 case TCSETS:
2045 case TCSETSW:
2046 case TCSETSF:
2047 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TCSET{S,SW,SF})", arg3,
2048 VKI_SIZEOF_STRUCT_TERMIOS );
2049 break;
2050 case TCGETS:
2051 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TCGETS)", arg3,
2052 VKI_SIZEOF_STRUCT_TERMIOS );
2053 break;
2054 case TCSETA:
2055 case TCSETAW:
2056 case TCSETAF:
2057 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TCSET{A,AW,AF})", arg3,
2058 VKI_SIZEOF_STRUCT_TERMIO );
2059 break;
2060 case TCGETA:
2061 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TCGETA)", arg3,
2062 VKI_SIZEOF_STRUCT_TERMIO );
2063 break;
2064 case TCSBRK:
2065 case TCXONC:
2066 case TCSBRKP:
2067 case TCFLSH:
2068 /* These just take an int by value */
2069 break;
2070 case TIOCGWINSZ:
2071 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TIOCGWINSZ)", arg3,
2072 sizeof(struct winsize) );
2073 break;
2074 case TIOCSWINSZ:
2075 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TIOCSWINSZ)", arg3,
2076 sizeof(struct winsize) );
2077 break;
2078 case TIOCLINUX:
2079 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TIOCLINUX)", arg3,
2080 sizeof(char *) );
2081 if (*(char *)arg3 == 11) {
2082 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TIOCLINUX, 11)",
2083 arg3, 2 * sizeof(char *) );
2084 }
2085 break;
2086 case TIOCGPGRP:
2087 /* Get process group ID for foreground processing group. */
2088 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TIOCGPGRP)", arg3,
2089 sizeof(pid_t) );
2090 break;
2091 case TIOCSPGRP:
2092 /* Set a process group ID? */
2093 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TIOCGPGRP)", arg3,
2094 sizeof(pid_t) );
2095 break;
2096 case TIOCGPTN: /* Get Pty Number (of pty-mux device) */
2097 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(TIOCGPTN)",
2098 arg3, sizeof(int) );
2099 break;
2100 case TIOCSCTTY:
2101 /* Just takes an int value. */
2102 break;
2103 case TIOCSPTLCK: /* Lock/unlock Pty */
2104 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(TIOCSPTLCK)",
2105 arg3, sizeof(int) );
2106 break;
2107 case FIONBIO:
2108 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(FIONBIO)",
2109 arg3, sizeof(int) );
2110 break;
2111 case FIOASYNC:
2112 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(FIOASYNC)",
2113 arg3, sizeof(int) );
2114 break;
2115 case FIONREAD: /* identical to SIOCINQ */
2116 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(FIONREAD)",
2117 arg3, sizeof(int) );
2118 break;
2119
2120 /* If you get compilation problems here, change the #if
2121 1 to #if 0 and get rid of <scsi/sg.h> in
2122 vg_unsafe.h. */
2123# if 1
2124 case SG_SET_COMMAND_Q:
2125 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SG_SET_COMMAND_Q)",
2126 arg3, sizeof(int) );
2127 break;
2128# if defined(SG_IO)
2129 case SG_IO:
2130 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SG_IO)", arg3,
2131 sizeof(struct sg_io_hdr) );
2132 break;
2133# endif /* SG_IO */
2134 case SG_GET_SCSI_ID:
2135 /* Note: sometimes sg_scsi_id is called sg_scsi_id_t */
2136 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SG_GET_SCSI_ID)", arg3,
2137 sizeof(struct sg_scsi_id) );
2138 break;
2139 case SG_SET_RESERVED_SIZE:
2140 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SG_SET_RESERVED_SIZE)",
2141 arg3, sizeof(int) );
2142 break;
2143 case SG_SET_TIMEOUT:
2144 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SG_SET_TIMEOUT)", arg3,
2145 sizeof(int) );
2146 break;
2147 case SG_GET_RESERVED_SIZE:
2148 SYSCALL_TRACK( pre_mem_write, tid,
2149 "ioctl(SG_GET_RESERVED_SIZE)", arg3,
2150 sizeof(int) );
2151 break;
2152 case SG_GET_TIMEOUT:
2153 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(SG_GET_TIMEOUT)", arg3,
2154 sizeof(int) );
2155 break;
2156 case SG_GET_VERSION_NUM:
2157 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SG_GET_VERSION_NUM)",
2158 arg3, sizeof(int) );
2159 break;
2160# endif
2161
2162 case IIOCGETCPS:
2163 /* In early 2.4 kernels, ISDN_MAX_CHANNELS was only defined
2164 * when KERNEL was. I never saw a larger value than 64 though */
2165# ifndef ISDN_MAX_CHANNELS
2166# define ISDN_MAX_CHANNELS 64
2167# endif
2168 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(IIOCGETCPS)", arg3,
2169 ISDN_MAX_CHANNELS
2170 * 2 * sizeof(unsigned long) );
2171 break;
2172 case IIOCNETGPN:
2173 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(IIOCNETGPN)",
2174 (UInt)&((isdn_net_ioctl_phone *)arg3)->name,
2175 sizeof(((isdn_net_ioctl_phone *)arg3)->name) );
2176 SYSCALL_TRACK( pre_mem_write, tid, "ioctl(IIOCNETGPN)", arg3,
2177 sizeof(isdn_net_ioctl_phone) );
2178 break;
2179
2180 /* These all use struct ifreq AFAIK */
2181 case SIOCGIFINDEX:
2182 case SIOCGIFFLAGS: /* get flags */
2183 case SIOCGIFHWADDR: /* Get hardware address */
2184 case SIOCGIFMTU: /* get MTU size */
2185 case SIOCGIFADDR: /* get PA address */
2186 case SIOCGIFNETMASK: /* get network PA mask */
2187 case SIOCGIFMETRIC: /* get metric */
2188 case SIOCGIFMAP: /* Get device parameters */
2189 case SIOCGIFTXQLEN: /* Get the tx queue length */
2190 case SIOCGIFDSTADDR: /* get remote PA address */
2191 case SIOCGIFBRDADDR: /* get broadcast PA address */
2192 case SIOCGIFNAME: /* get iface name */
2193 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SIOCGIFINDEX)", arg3,
2194 sizeof(struct ifreq));
2195 break;
2196 case SIOCGIFCONF: /* get iface list */
2197 /* WAS:
2198 SYSCALL_TRACK( pre_mem_write,"ioctl(SIOCGIFCONF)", arg3,
2199 sizeof(struct ifconf));
2200 KERNEL_DO_SYSCALL(tid,res);
2201 if (!VG_(is_kerror)(res) && res == 0)
2202 VG_TRACK( post_mem_write,arg3, sizeof(struct ifconf));
2203 */
2204 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(SIOCGIFCONF)", arg3,
2205 sizeof(struct ifconf));
2206 if ( arg3 ) {
2207 // TODO len must be readable and writable
2208 // buf pointer only needs to be readable
2209 struct ifconf *ifc = (struct ifconf *) arg3;
2210 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SIOCGIFCONF).ifc_buf",
2211 (Addr)(ifc->ifc_buf), (UInt)(ifc->ifc_len) );
2212 }
2213 break;
2214 case SIOCGSTAMP:
2215 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SIOCGSTAMP)", arg3,
2216 sizeof(struct timeval));
2217 break;
2218 /* SIOCOUTQ is an ioctl that, when called on a socket, returns
2219 the number of bytes currently in that socket's send buffer.
2220 It writes this value as an int to the memory location
2221 indicated by the third argument of ioctl(2). */
2222 case SIOCOUTQ:
2223 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SIOCOUTQ)", arg3,
2224 sizeof(int));
2225 break;
2226 case SIOCGRARP: /* get RARP table entry */
2227 case SIOCGARP: /* get ARP table entry */
2228 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SIOCGARP)", arg3,
2229 sizeof(struct arpreq));
2230 break;
2231
2232 case SIOCSIFFLAGS: /* set flags */
2233 case SIOCSIFMAP: /* Set device parameters */
2234 case SIOCSIFTXQLEN: /* Set the tx queue length */
2235 case SIOCSIFDSTADDR: /* set remote PA address */
2236 case SIOCSIFBRDADDR: /* set broadcast PA address */
2237 case SIOCSIFNETMASK: /* set network PA mask */
2238 case SIOCSIFMETRIC: /* set metric */
2239 case SIOCSIFADDR: /* set PA address */
2240 case SIOCSIFMTU: /* set MTU size */
2241 case SIOCSIFHWADDR: /* set hardware address */
2242 SYSCALL_TRACK( pre_mem_read,tid,"ioctl(SIOCSIFFLAGS)", arg3,
2243 sizeof(struct ifreq));
2244 break;
2245 /* Routing table calls. */
2246 case SIOCADDRT: /* add routing table entry */
2247 case SIOCDELRT: /* delete routing table entry */
2248 SYSCALL_TRACK( pre_mem_read,tid,"ioctl(SIOCADDRT/DELRT)", arg3,
2249 sizeof(struct rtentry));
2250 break;
2251
2252 /* RARP cache control calls. */
2253 case SIOCDRARP: /* delete RARP table entry */
2254 case SIOCSRARP: /* set RARP table entry */
2255 /* ARP cache control calls. */
2256 case SIOCSARP: /* set ARP table entry */
2257 case SIOCDARP: /* delete ARP table entry */
2258 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(SIOCSIFFLAGS)", arg3,
2259 sizeof(struct ifreq));
2260 break;
2261
2262 case SIOCSPGRP:
2263 SYSCALL_TRACK( pre_mem_read, tid, "ioctl(SIOCSPGRP)", arg3,
2264 sizeof(int) );
2265 break;
2266
2267 /* linux/soundcard interface (OSS) */
2268 case SNDCTL_SEQ_GETOUTCOUNT:
2269 case SNDCTL_SEQ_GETINCOUNT:
2270 case SNDCTL_SEQ_PERCMODE:
2271 case SNDCTL_SEQ_TESTMIDI:
2272 case SNDCTL_SEQ_RESETSAMPLES:
2273 case SNDCTL_SEQ_NRSYNTHS:
2274 case SNDCTL_SEQ_NRMIDIS:
2275 case SNDCTL_SEQ_GETTIME:
2276 case SNDCTL_DSP_GETFMTS:
2277 case SNDCTL_DSP_GETTRIGGER:
2278 case SNDCTL_DSP_GETODELAY:
2279# if defined(SNDCTL_DSP_GETSPDIF)
2280 case SNDCTL_DSP_GETSPDIF:
2281# endif
2282 case SNDCTL_DSP_GETCAPS:
2283 case SOUND_PCM_READ_RATE:
2284 case SOUND_PCM_READ_CHANNELS:
2285 case SOUND_PCM_READ_BITS:
2286 case (SOUND_PCM_READ_BITS|0x40000000): /* what the fuck ? */
2287 case SOUND_PCM_READ_FILTER:
2288 SYSCALL_TRACK( pre_mem_write,tid,
2289 "ioctl(SNDCTL_XXX|SOUND_XXX (SIOR, int))",
2290 arg3,
2291 sizeof(int));
2292 break;
2293 case SNDCTL_SEQ_CTRLRATE:
2294 case SNDCTL_DSP_SPEED:
2295 case SNDCTL_DSP_STEREO:
2296 case SNDCTL_DSP_GETBLKSIZE:
2297 case SNDCTL_DSP_CHANNELS:
2298 case SOUND_PCM_WRITE_FILTER:
2299 case SNDCTL_DSP_SUBDIVIDE:
2300 case SNDCTL_DSP_SETFRAGMENT:
2301# if defined(SNDCTL_DSP_GETCHANNELMASK)
2302 case SNDCTL_DSP_GETCHANNELMASK:
2303# endif
2304# if defined(SNDCTL_DSP_BIND_CHANNEL)
2305 case SNDCTL_DSP_BIND_CHANNEL:
2306# endif
2307 case SNDCTL_TMR_TIMEBASE:
2308 case SNDCTL_TMR_TEMPO:
2309 case SNDCTL_TMR_SOURCE:
2310 case SNDCTL_MIDI_PRETIME:
2311 case SNDCTL_MIDI_MPUMODE:
2312 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(SNDCTL_XXX|SOUND_XXX "
2313 "(SIOWR, int))",
2314 arg3, sizeof(int));
2315 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(SNDCTL_XXX|SOUND_XXX "
2316 "(SIOWR, int))",
2317 arg3, sizeof(int));
2318 break;
2319 case SNDCTL_DSP_GETOSPACE:
2320 case SNDCTL_DSP_GETISPACE:
2321 SYSCALL_TRACK( pre_mem_write,tid,
2322 "ioctl(SNDCTL_XXX|SOUND_XXX "
2323 "(SIOR, audio_buf_info))", arg3,
2324 sizeof(audio_buf_info));
2325 break;
2326 case SNDCTL_DSP_SETTRIGGER:
2327 SYSCALL_TRACK( pre_mem_read,tid,
2328 "ioctl(SNDCTL_XXX|SOUND_XXX (SIOW, int))",
2329 arg3, sizeof(int));
2330 break;
2331
2332 case SNDCTL_DSP_POST:
2333 case SNDCTL_DSP_RESET:
2334 case SNDCTL_DSP_SYNC:
2335 case SNDCTL_DSP_SETSYNCRO:
2336 case SNDCTL_DSP_SETDUPLEX:
2337 break;
2338
2339 /* Real Time Clock (/dev/rtc) ioctls */
2340# ifndef GLIBC_2_1
2341 case RTC_UIE_ON:
2342 case RTC_UIE_OFF:
2343 case RTC_AIE_ON:
2344 case RTC_AIE_OFF:
2345 case RTC_PIE_ON:
2346 case RTC_PIE_OFF:
2347 case RTC_IRQP_SET:
2348 break;
2349 case RTC_RD_TIME:
2350 case RTC_ALM_READ:
2351 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(RTC_RD_TIME/ALM_READ)",
2352 arg3, sizeof(struct rtc_time));
2353 break;
2354 case RTC_ALM_SET:
2355 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(RTC_ALM_SET)", arg3,
2356 sizeof(struct rtc_time));
2357 break;
2358 case RTC_IRQP_READ:
2359 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(RTC_IRQP_READ)", arg3,
2360 sizeof(unsigned long));
2361 break;
2362# endif /* GLIBC_2_1 */
2363
2364# ifdef BLKGETSIZE
2365 case BLKGETSIZE:
2366 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(BLKGETSIZE)", arg3,
2367 sizeof(unsigned long));
2368 break;
2369# endif /* BLKGETSIZE */
2370
2371 /* CD ROM stuff (??) */
2372 case CDROMSUBCHNL:
2373 SYSCALL_TRACK( pre_mem_read,tid,
2374 "ioctl(CDROMSUBCHNL (cdsc_format, char))",
2375 (int) &(((struct cdrom_subchnl *) arg3)->cdsc_format),
2376 sizeof(((struct cdrom_subchnl *) arg3)->cdsc_format));
2377 SYSCALL_TRACK( pre_mem_write,tid,
2378 "ioctl(CDROMSUBCHNL)", arg3,
2379 sizeof(struct cdrom_subchnl));
2380 break;
2381 case CDROMREADTOCHDR:
2382 SYSCALL_TRACK( pre_mem_write,tid,
2383 "ioctl(CDROMREADTOCHDR)", arg3,
2384 sizeof(struct cdrom_tochdr));
2385 break;
2386 case CDROMREADTOCENTRY:
2387 SYSCALL_TRACK( pre_mem_read,tid,
2388 "ioctl(CDROMREADTOCENTRY (cdte_format, char))",
2389 (int) &(((struct cdrom_tocentry *) arg3)->cdte_format),
2390 sizeof(((struct cdrom_tocentry *) arg3)->cdte_format));
2391 SYSCALL_TRACK( pre_mem_read,tid,
2392 "ioctl(CDROMREADTOCENTRY (cdte_track, char))",
2393 (int) &(((struct cdrom_tocentry *) arg3)->cdte_track),
2394 sizeof(((struct cdrom_tocentry *) arg3)->cdte_track));
2395 SYSCALL_TRACK( pre_mem_write,tid,
2396 "ioctl(CDROMREADTOCENTRY)", arg3,
2397 sizeof(struct cdrom_tocentry));
2398 break;
2399 case CDROMPLAYMSF:
2400 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(CDROMPLAYMSF)", arg3,
2401 sizeof(struct cdrom_msf));
2402 break;
2403 /* The following two are probably bogus (should check args
2404 for readability). JRS 20021117 */
2405 case CDROM_DRIVE_STATUS: /* 0x5326 */
2406 case CDROM_CLEAR_OPTIONS: /* 0x5321 */
2407 break;
2408
2409 /* We don't have any specific information on it, so
2410 try to do something reasonable based on direction and
2411 size bits. The encoding scheme is described in
2412 /usr/include/asm/ioctl.h.
2413
2414 According to Simon Hausmann, _IOC_READ means the kernel
2415 writes a value to the ioctl value passed from the user
2416 space and the other way around with _IOC_WRITE. */
2417 default: {
2418 UInt dir = _IOC_DIR(arg2);
2419 UInt size = _IOC_SIZE(arg2);
2420 if (VG_(strstr)(VG_(clo_weird_hacks), "lax-ioctls") != NULL) {
2421 /*
2422 * Be very lax about ioctl handling; the only
2423 * assumption is that the size is correct. Doesn't
2424 * require the full buffer to be initialized when
2425 * writing. Without this, using some device
2426 * drivers with a large number of strange ioctl
2427 * commands becomes very tiresome.
2428 */
2429 } else if (/* size == 0 || */ dir == _IOC_NONE) {
2430 static Int moans = 3;
2431 if (moans > 0) {
2432 moans--;
2433 VG_(message)(Vg_UserMsg,
2434 "Warning: noted but unhandled ioctl 0x%x"
2435 " with no size/direction hints",
2436 arg2);
2437 VG_(message)(Vg_UserMsg,
2438 " This could cause spurious value errors"
2439 " to appear.");
2440 VG_(message)(Vg_UserMsg,
2441 " See README_MISSING_SYSCALL_OR_IOCTL for "
2442 "guidance on writing a proper wrapper." );
2443 }
2444 } else {
2445 if ((dir & _IOC_WRITE) && size > 0)
2446 SYSCALL_TRACK( pre_mem_read,tid, "ioctl(generic)",
2447 arg3, size);
2448 if ((dir & _IOC_READ) && size > 0)
2449 SYSCALL_TRACK( pre_mem_write,tid, "ioctl(generic)",
2450 arg3, size);
2451 }
2452 break;
2453 }
2454 }
2455}
2456
2457POST(ioctl)
2458{
2459 /* int ioctl(int d, int request, ...)
2460 [The "third" argument is traditionally char *argp,
2461 and will be so named for this discussion.]
2462 */
2463 /*
2464 VG_(message)(
2465 Vg_DebugMsg,
2466 "is an IOCTL, request = 0x%x, d = %d, argp = 0x%x",
2467 arg2,arg1,arg3);
2468 */
2469 MAYBE_PRINTF("ioctl ( %d, 0x%x, %p )\n",arg1,arg2,arg3);
2470 switch (arg2 /* request */) {
2471 case TCSETS:
2472 case TCSETSW:
2473 case TCSETSF:
2474 break;
2475 case TCGETS:
2476 if (res == 0)
2477 VG_TRACK( post_mem_write, arg3, VKI_SIZEOF_STRUCT_TERMIOS );
2478 break;
2479 case TCSETA:
2480 case TCSETAW:
2481 case TCSETAF:
2482 break;
2483 case TCGETA:
2484 if (res == 0)
2485 VG_TRACK( post_mem_write, arg3, VKI_SIZEOF_STRUCT_TERMIO );
2486 break;
2487 case TCSBRK:
2488 case TCXONC:
2489 case TCSBRKP:
2490 case TCFLSH:
2491 break;
2492 case TIOCGWINSZ:
2493 if (res == 0)
2494 VG_TRACK( post_mem_write, arg3, sizeof(struct winsize) );
2495 break;
2496 case TIOCSWINSZ:
2497 break;
2498 case TIOCLINUX:
2499 if (res == 0)
2500 VG_TRACK( post_mem_write, arg3, sizeof(char *) );
2501 break;
2502 case TIOCGPGRP:
2503 /* Get process group ID for foreground processing group. */
2504 if (res == 0)
2505 VG_TRACK( post_mem_write, arg3, sizeof(pid_t) );
2506 break;
2507 case TIOCSPGRP:
2508 /* Set a process group ID? */
2509 if (res == 0)
2510 VG_TRACK( post_mem_write, arg3, sizeof(pid_t) );
2511 break;
2512 case TIOCGPTN: /* Get Pty Number (of pty-mux device) */
2513 if (res == 0)
2514 VG_TRACK( post_mem_write, arg3, sizeof(int));
2515 break;
2516 case TIOCSCTTY:
2517 break;
2518 case TIOCSPTLCK: /* Lock/unlock Pty */
2519 break;
2520 case FIONBIO:
2521 break;
2522 case FIOASYNC:
2523 break;
2524 case FIONREAD: /* identical to SIOCINQ */
2525 if (res == 0)
2526 VG_TRACK( post_mem_write, arg3, sizeof(int) );
2527 break;
2528
2529 /* If you get compilation problems here, change the #if
2530 1 to #if 0 and get rid of <scsi/sg.h> in
2531 vg_unsafe.h. */
2532# if 1
2533 case SG_SET_COMMAND_Q:
2534 break;
2535# if defined(SG_IO)
2536 case SG_IO:
2537 if (res == 0)
2538 VG_TRACK( post_mem_write,arg3, sizeof(struct sg_io_hdr));
2539 break;
2540# endif /* SG_IO */
2541 case SG_GET_SCSI_ID:
2542 if (res == 0)
2543 VG_TRACK( post_mem_write,arg3, sizeof(struct sg_scsi_id));
2544 break;
2545 case SG_SET_RESERVED_SIZE:
2546 break;
2547 case SG_SET_TIMEOUT:
2548 break;
2549 case SG_GET_RESERVED_SIZE:
2550 if (res == 0)
2551 VG_TRACK( post_mem_write,arg3, sizeof(int));
2552 break;
2553 case SG_GET_TIMEOUT:
2554 if (res == 0)
2555 VG_TRACK( post_mem_write,arg3, sizeof(int));
2556 break;
2557 case SG_GET_VERSION_NUM:
2558 break;
2559# endif
2560
2561 case IIOCGETCPS:
2562 /* In early 2.4 kernels, ISDN_MAX_CHANNELS was only defined
2563 * when KERNEL was. I never saw a larger value than 64 though */
2564# ifndef ISDN_MAX_CHANNELS
2565# define ISDN_MAX_CHANNELS 64
2566# endif
2567 if (res == 0)
2568 VG_TRACK( post_mem_write, arg3, ISDN_MAX_CHANNELS
2569 * 2 * sizeof(unsigned long) );
2570 break;
2571 case IIOCNETGPN:
2572 if (res == 0)
2573 VG_TRACK( post_mem_write, arg3, sizeof(isdn_net_ioctl_phone) );
2574 break;
2575
2576 /* These all use struct ifreq AFAIK */
2577 case SIOCGIFINDEX:
2578 case SIOCGIFFLAGS: /* get flags */
2579 case SIOCGIFHWADDR: /* Get hardware address */
2580 case SIOCGIFMTU: /* get MTU size */
2581 case SIOCGIFADDR: /* get PA address */
2582 case SIOCGIFNETMASK: /* get network PA mask */
2583 case SIOCGIFMETRIC: /* get metric */
2584 case SIOCGIFMAP: /* Get device parameters */
2585 case SIOCGIFTXQLEN: /* Get the tx queue length */
2586 case SIOCGIFDSTADDR: /* get remote PA address */
2587 case SIOCGIFBRDADDR: /* get broadcast PA address */
2588 case SIOCGIFNAME: /* get iface name */
2589 if (res == 0)
2590 VG_TRACK( post_mem_write,arg3, sizeof(struct ifreq));
2591 break;
2592 case SIOCGIFCONF: /* get iface list */
2593 /* WAS:
2594 SYSCALL_TRACK( pre_mem_write,"ioctl(SIOCGIFCONF)", arg3,
2595 sizeof(struct ifconf));
2596 KERNEL_DO_SYSCALL(tid,res);
2597 if (!VG_(is_kerror)(res) && res == 0)
2598 VG_TRACK( post_mem_write,arg3, sizeof(struct ifconf));
2599 */
2600 if (res == 0 && arg3 ) {
2601 struct ifconf *ifc = (struct ifconf *) arg3;
2602 if (ifc->ifc_buf != NULL)
2603 VG_TRACK( post_mem_write, (Addr)(ifc->ifc_buf),
2604 (UInt)(ifc->ifc_len) );
2605 }
2606 break;
2607 case SIOCGSTAMP:
2608 if (res == 0)
2609 VG_TRACK( post_mem_write,arg3, sizeof(struct timeval));
2610 break;
2611 /* SIOCOUTQ is an ioctl that, when called on a socket, returns
2612 the number of bytes currently in that socket's send buffer.
2613 It writes this value as an int to the memory location
2614 indicated by the third argument of ioctl(2). */
2615 case SIOCOUTQ:
2616 if (res == 0)
2617 VG_TRACK( post_mem_write,arg3, sizeof(int));
2618 break;
2619 case SIOCGRARP: /* get RARP table entry */
2620 case SIOCGARP: /* get ARP table entry */
2621 if (res == 0)
2622 VG_TRACK( post_mem_write,arg3, sizeof(struct arpreq));
2623 break;
2624
2625 case SIOCSIFFLAGS: /* set flags */
2626 case SIOCSIFMAP: /* Set device parameters */
2627 case SIOCSIFTXQLEN: /* Set the tx queue length */
2628 case SIOCSIFDSTADDR: /* set remote PA address */
2629 case SIOCSIFBRDADDR: /* set broadcast PA address */
2630 case SIOCSIFNETMASK: /* set network PA mask */
2631 case SIOCSIFMETRIC: /* set metric */
2632 case SIOCSIFADDR: /* set PA address */
2633 case SIOCSIFMTU: /* set MTU size */
2634 case SIOCSIFHWADDR: /* set hardware address */
2635 break;
2636 /* Routing table calls. */
2637 case SIOCADDRT: /* add routing table entry */
2638 case SIOCDELRT: /* delete routing table entry */
2639 break;
2640
2641 /* RARP cache control calls. */
2642 case SIOCDRARP: /* delete RARP table entry */
2643 case SIOCSRARP: /* set RARP table entry */
2644 /* ARP cache control calls. */
2645 case SIOCSARP: /* set ARP table entry */
2646 case SIOCDARP: /* delete ARP table entry */
2647 break;
2648
2649 case SIOCSPGRP:
2650 break;
2651
2652 /* linux/soundcard interface (OSS) */
2653 case SNDCTL_SEQ_GETOUTCOUNT:
2654 case SNDCTL_SEQ_GETINCOUNT:
2655 case SNDCTL_SEQ_PERCMODE:
2656 case SNDCTL_SEQ_TESTMIDI:
2657 case SNDCTL_SEQ_RESETSAMPLES:
2658 case SNDCTL_SEQ_NRSYNTHS:
2659 case SNDCTL_SEQ_NRMIDIS:
2660 case SNDCTL_SEQ_GETTIME:
2661 case SNDCTL_DSP_GETFMTS:
2662 case SNDCTL_DSP_GETTRIGGER:
2663 case SNDCTL_DSP_GETODELAY:
2664# if defined(SNDCTL_DSP_GETSPDIF)
2665 case SNDCTL_DSP_GETSPDIF:
2666# endif
2667 case SNDCTL_DSP_GETCAPS:
2668 case SOUND_PCM_READ_RATE:
2669 case SOUND_PCM_READ_CHANNELS:
2670 case SOUND_PCM_READ_BITS:
2671 case (SOUND_PCM_READ_BITS|0x40000000): /* what the fuck ? */
2672 case SOUND_PCM_READ_FILTER:
2673 if (res == 0)
2674 VG_TRACK( post_mem_write,arg3, sizeof(int));
2675 break;
2676 case SNDCTL_SEQ_CTRLRATE:
2677 case SNDCTL_DSP_SPEED:
2678 case SNDCTL_DSP_STEREO:
2679 case SNDCTL_DSP_GETBLKSIZE:
2680 case SNDCTL_DSP_CHANNELS:
2681 case SOUND_PCM_WRITE_FILTER:
2682 case SNDCTL_DSP_SUBDIVIDE:
2683 case SNDCTL_DSP_SETFRAGMENT:
2684# if defined(SNDCTL_DSP_GETCHANNELMASK)
2685 case SNDCTL_DSP_GETCHANNELMASK:
2686# endif
2687# if defined(SNDCTL_DSP_BIND_CHANNEL)
2688 case SNDCTL_DSP_BIND_CHANNEL:
2689# endif
2690 case SNDCTL_TMR_TIMEBASE:
2691 case SNDCTL_TMR_TEMPO:
2692 case SNDCTL_TMR_SOURCE:
2693 case SNDCTL_MIDI_PRETIME:
2694 case SNDCTL_MIDI_MPUMODE:
2695 break;
2696 case SNDCTL_DSP_GETOSPACE:
2697 case SNDCTL_DSP_GETISPACE:
2698 if (res == 0)
2699 VG_TRACK( post_mem_write,arg3, sizeof(audio_buf_info));
2700 break;
2701 case SNDCTL_DSP_SETTRIGGER:
2702 break;
2703
2704 case SNDCTL_DSP_POST:
2705 case SNDCTL_DSP_RESET:
2706 case SNDCTL_DSP_SYNC:
2707 case SNDCTL_DSP_SETSYNCRO:
2708 case SNDCTL_DSP_SETDUPLEX:
2709 break;
2710
2711 /* Real Time Clock (/dev/rtc) ioctls */
2712# ifndef GLIBC_2_1
2713 case RTC_UIE_ON:
2714 case RTC_UIE_OFF:
2715 case RTC_AIE_ON:
2716 case RTC_AIE_OFF:
2717 case RTC_PIE_ON:
2718 case RTC_PIE_OFF:
2719 case RTC_IRQP_SET:
2720 break;
2721 case RTC_RD_TIME:
2722 case RTC_ALM_READ:
2723 if (res == 0)
2724 VG_TRACK( post_mem_write,arg3, sizeof(struct rtc_time));
2725 break;
2726 case RTC_ALM_SET:
2727 break;
2728 case RTC_IRQP_READ:
2729 if(res == 0)
2730 VG_TRACK( post_mem_write,arg3, sizeof(unsigned long));
2731 break;
2732# endif /* GLIBC_2_1 */
2733
2734# ifdef BLKGETSIZE
2735 case BLKGETSIZE:
2736 if (res == 0)
2737 VG_TRACK( post_mem_write,arg3, sizeof(unsigned long));
2738 break;
2739# endif /* BLKGETSIZE */
2740
2741 /* CD ROM stuff (??) */
2742 case CDROMSUBCHNL:
2743 if (res == 0)
2744 VG_TRACK( post_mem_write,arg3, sizeof(struct cdrom_subchnl));
2745 break;
2746 case CDROMREADTOCHDR:
2747 if (res == 0)
2748 VG_TRACK( post_mem_write,arg3, sizeof(struct cdrom_tochdr));
2749 break;
2750 case CDROMREADTOCENTRY:
2751 if (res == 0)
2752 VG_TRACK( post_mem_write,arg3, sizeof(struct cdrom_tochdr));
2753 break;
2754 case CDROMPLAYMSF:
2755 break;
2756 /* The following two are probably bogus (should check args
2757 for readability). JRS 20021117 */
2758 case CDROM_DRIVE_STATUS: /* 0x5326 */
2759 case CDROM_CLEAR_OPTIONS: /* 0x5321 */
2760 break;
2761
2762 /* We don't have any specific information on it, so
2763 try to do something reasonable based on direction and
2764 size bits. The encoding scheme is described in
2765 /usr/include/asm/ioctl.h.
2766
2767 According to Simon Hausmann, _IOC_READ means the kernel
2768 writes a value to the ioctl value passed from the user
2769 space and the other way around with _IOC_WRITE. */
2770 default: {
2771 UInt dir = _IOC_DIR(arg2);
2772 UInt size = _IOC_SIZE(arg2);
2773 if (size > 0 && (dir & _IOC_READ)
2774 && res == 0
2775 && arg3 != (Addr)NULL)
2776 VG_TRACK( post_mem_write,arg3, size);
2777 break;
2778 }
2779 }
2780}
2781
2782PRE(kill)
2783{
2784 /* int kill(pid_t pid, int sig); */
2785 MAYBE_PRINTF("kill ( %d, %d )\n", arg1,arg2);
2786 if (arg2 == VKI_SIGVGINT || arg2 == VKI_SIGVGKILL)
2787 res = -VKI_EINVAL;
2788}
2789
2790POST(kill)
2791{
2792 /* If this was a self-kill then wait for a signal to be
2793 delivered to any thread before claiming the kill is done. */
2794 if (res >= 0 && /* if it was successful */
2795 arg2 != 0 && /* if a real signal */
2796 !VG_(is_sig_ign)(arg2) && /* that isn't ignored and */
2797 !VG_(ksigismember)(&tst->eff_sig_mask, arg2) && /* we're not blocking it */
2798 (arg1 == VG_(getpid)() || /* directed at us or */
2799 arg1 == -1 || /* directed at everyone or */
2800 arg1 == 0 || /* directed at whole group or */
2801 -arg1 == VG_(getpgrp)())) { /* directed at our group... */
2802 /* ...then wait for that signal to be delivered to someone
2803 (might be us, might be someone else who doesn't have it
2804 blocked) */
2805 VG_(proxy_waitsig)();
2806 }
2807}
2808
2809PRE(link)
2810{
2811 /* int link(const char *oldpath, const char *newpath); */
2812 MAYBE_PRINTF("link ( %p, %p)\n", arg1, arg2);
2813 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "link(oldpath)", arg1);
2814 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "link(newpath)", arg2);
2815}
2816
2817PRE(lseek)
2818{
2819 /* off_t lseek(int fildes, off_t offset, int whence); */
2820 MAYBE_PRINTF("lseek ( %d, %d, %d )\n",arg1,arg2,arg3);
2821}
2822
2823PRE(_llseek)
2824{
2825 /* int _llseek(unsigned int fd, unsigned long offset_high,
2826 unsigned long offset_low,
2827 loff_t * result, unsigned int whence); */
2828 MAYBE_PRINTF("llseek ( %d, 0x%x, 0x%x, %p, %d )\n",
2829 arg1,arg2,arg3,arg4,arg5);
2830 SYSCALL_TRACK( pre_mem_write, tid, "llseek(result)", arg4,
2831 sizeof(loff_t));
2832}
2833
2834POST(_llseek)
2835{
2836 if (res == 0)
2837 VG_TRACK( post_mem_write, arg4, sizeof(loff_t) );
2838}
2839
2840PRE(lstat)
2841{
2842 /* int lstat(const char *file_name, struct stat *buf); */
2843 MAYBE_PRINTF("lstat ( %p, %p )\n",arg1,arg2);
2844 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "lstat(file_name)", arg1 );
2845 SYSCALL_TRACK( pre_mem_write, tid, "lstat(buf)", arg2,
2846 sizeof(struct stat) );
2847}
2848
2849POST(lstat)
2850{
2851 if (res == 0) {
2852 VG_TRACK( post_mem_write, arg2, sizeof(struct stat) );
2853 }
2854}
2855
2856PRE(lstat64)
2857{
2858 /* int lstat64(const char *file_name, struct stat64 *buf); */
2859 MAYBE_PRINTF("lstat64 ( %p, %p )\n",arg1,arg2);
2860 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "lstat64(file_name)", arg1 );
2861 SYSCALL_TRACK( pre_mem_write, tid, "lstat64(buf)", arg2,
2862 sizeof(struct stat64) );
2863}
2864
2865POST(lstat64)
2866{
2867 if (res == 0) {
2868 VG_TRACK( post_mem_write, arg2, sizeof(struct stat64) );
2869 }
2870}
2871
2872PRE(mkdir)
2873{
2874 /* int mkdir(const char *pathname, mode_t mode); */
2875 MAYBE_PRINTF("mkdir ( %p, %d )\n", arg1,arg2);
2876 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "mkdir(pathname)", arg1 );
2877}
2878
2879PRE(mmap2)
2880{
2881 /* My impression is that this is exactly like __NR_mmap
2882 except that all 6 args are passed in regs, rather than in
2883 a memory-block. */
2884 /* void* mmap(void *start, size_t length, int prot,
2885 int flags, int fd, off_t offset);
2886 */
2887 MAYBE_PRINTF("mmap2 ( %p, %d, %d, %d, %d, %d )\n",
2888 arg1, arg2, arg3, arg4, arg5, arg6 );
2889}
2890
2891POST(mmap2)
2892{
2893 mmap_segment( (Addr)res, arg2, arg3, arg5 );
2894}
2895
2896PRE(mmap)
2897{
2898 /* void* mmap(void *start, size_t length, int prot,
2899 int flags, int fd, off_t offset);
2900 */
2901
2902 UInt* arg_block = (UInt*)arg1;
2903 UInt a1, a2, a3, a4, a5, a6;
2904
2905 SYSCALL_TRACK( pre_mem_read, tid, "mmap(args)", arg1, 6*sizeof(UInt) );
2906
2907 a1 = arg_block[0];
2908 a2 = arg_block[1];
2909 a3 = arg_block[2];
2910 a4 = arg_block[3];
2911 a5 = arg_block[4];
2912 a6 = arg_block[5];
2913 MAYBE_PRINTF("mmap ( %p, %d, %d, %d, %d, %d )\n",
2914 a1, a2, a3, a4, a5, a6 );
2915}
2916
2917POST(mmap)
2918{
2919 UInt* arg_block = (UInt*)arg1;
2920 UInt a2, a3, a5;
2921
2922 a2 = arg_block[1];
2923 a3 = arg_block[2];
2924 a5 = arg_block[4];
2925
2926 mmap_segment( (Addr)res, a2, a3, a5 );
2927}
2928
2929PRE(mprotect)
2930{
2931 /* int mprotect(const void *addr, size_t len, int prot); */
2932 /* should addr .. addr+len-1 be checked before the call? */
2933 MAYBE_PRINTF("mprotect ( %p, %d, %d )\n", arg1,arg2,arg3);
2934}
2935
2936POST(mprotect)
2937{
2938 mprotect_segment( arg1, arg2, arg3 );
2939}
2940
2941PRE(munmap)
2942{
2943 /* int munmap(void *start, size_t length); */
2944 /* should start .. start+length-1 be checked before the call? */
2945 MAYBE_PRINTF("munmap ( %p, %d )\n", arg1,arg2);
2946}
2947
2948POST(munmap)
2949{
2950 munmap_segment( arg1, arg2 );
2951}
2952
2953PRE(nanosleep)
2954{
2955 /* int nanosleep(const struct timespec *req, struct timespec *rem); */
2956 MAYBE_PRINTF("nanosleep ( %p, %p )\n", arg1,arg2);
2957 SYSCALL_TRACK( pre_mem_read, tid, "nanosleep(req)", arg1,
2958 sizeof(struct timespec) );
2959 if (arg2 != (UInt)NULL)
2960 SYSCALL_TRACK( pre_mem_write, tid, "nanosleep(rem)", arg2,
2961 sizeof(struct timespec) );
2962}
2963
2964POST(nanosleep)
2965{
2966 /* Somewhat bogus ... is only written by the kernel if
2967 res == -1 && errno == EINTR. */
2968 if (arg2 != (UInt)NULL)
2969 VG_TRACK( post_mem_write, arg2, sizeof(struct timespec) );
2970}
2971
2972PRE(_newselect)
2973{
2974 /* int select(int n,
2975 fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
2976 struct timeval *timeout);
2977 */
2978 MAYBE_PRINTF("newselect ( %d, %p, %p, %p, %p )\n",
2979 arg1,arg2,arg3,arg4,arg5);
2980 if (arg2 != 0)
2981 SYSCALL_TRACK( pre_mem_read, tid, "newselect(readfds)",
2982 arg2, arg1/8 /* __FD_SETSIZE/8 */ );
2983 if (arg3 != 0)
2984 SYSCALL_TRACK( pre_mem_read, tid, "newselect(writefds)",
2985 arg3, arg1/8 /* __FD_SETSIZE/8 */ );
2986 if (arg4 != 0)
2987 SYSCALL_TRACK( pre_mem_read, tid, "newselect(exceptfds)",
2988 arg4, arg1/8 /* __FD_SETSIZE/8 */ );
2989 if (arg5 != 0)
2990 SYSCALL_TRACK( pre_mem_read, tid, "newselect(timeout)", arg5,
2991 sizeof(struct timeval) );
2992}
2993
2994PRE(open)
2995{
2996 /* int open(const char *pathname, int flags); */
2997 MAYBE_PRINTF("open ( %p(%s), %d ) --> ",arg1,arg1,arg2);
2998 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "open(pathname)", arg1 );
2999}
3000
3001POST(open)
3002{
3003 if (!fd_allowed(res, "open", tid)) {
3004 VG_(close)(res);
3005 res = -VKI_EMFILE;
3006 }
3007 MAYBE_PRINTF("%d\n",res);
3008}
3009
3010PRE(read)
3011{
3012 /* size_t read(int fd, void *buf, size_t count); */
3013 MAYBE_PRINTF("read ( %d, %p, %d )\n", arg1, arg2, arg3);
3014
3015 if (!fd_allowed(arg1, "read", tid))
3016 res = -VKI_EBADF;
3017}
3018
3019POST(read)
3020{
3021 if (res > 0)
3022 VG_TRACK(post_mem_write, arg2, res);
3023}
3024
3025PRE(write)
3026{
3027 /* size_t write(int fd, const void *buf, size_t count); */
3028 MAYBE_PRINTF("write ( %d, %p, %d )\n", arg1, arg2, arg3);
3029 if (!fd_allowed(arg1, "write", tid))
3030 res = -VKI_EBADF;
3031 else
3032 SYSCALL_TRACK( pre_mem_read, tid, "write(buf)", arg2, arg3 );
3033}
3034
3035PRE(creat)
3036{
3037 /* int creat(const char *pathname, mode_t mode); */
3038 MAYBE_PRINTF("creat ( %p(%s), %d ) --> ",arg1,arg1,arg2);
3039 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "creat(pathname)", arg1 );
3040}
3041
3042POST(creat)
3043{
3044 if (!fd_allowed(res, "creat", tid)) {
3045 VG_(close)(res);
3046 res = -VKI_EMFILE;
3047 }
3048 MAYBE_PRINTF("%d\n",res);
3049}
3050
3051PRE(pipe)
3052{
3053 /* int pipe(int filedes[2]); */
3054 MAYBE_PRINTF("pipe ( %p ) ...\n", arg1);
3055 SYSCALL_TRACK( pre_mem_write, tid, "pipe(filedes)",
3056 arg1, 2*sizeof(int) );
3057}
3058
3059POST(pipe)
3060{
3061 Int *p = (Int *)arg1;
3062
3063 if (!fd_allowed(p[0], "pipe", tid) ||
3064 !fd_allowed(p[1], "pipe", tid)) {
3065 VG_(close)(p[0]);
3066 VG_(close)(p[1]);
3067 res = -VKI_EMFILE;
3068 } else
3069 VG_TRACK( post_mem_write, arg1, 2*sizeof(int) );
3070
3071 MAYBE_PRINTF("SYSCALL[%d] pipe --> %d (rd %d, wr %d)\n",
3072 VG_(getpid)(), res,
3073 ((UInt*)arg1)[0], ((UInt*)arg1)[1] );
3074}
3075
3076PRE(poll)
3077{
3078 /* struct pollfd {
3079 int fd; -- file descriptor
3080 short events; -- requested events
3081 short revents; -- returned events
3082 };
3083 int poll(struct pollfd *ufds, unsigned int nfds,
3084 int timeout)
3085 */
3086 MAYBE_PRINTF("poll ( %p, %d, %d )\n",arg1,arg2,arg3);
3087 /* In fact some parts of this struct should be readable too.
3088 This should be fixed properly. */
3089 SYSCALL_TRACK( pre_mem_write, tid, "poll(ufds)",
3090 arg1, arg2 * sizeof(struct pollfd) );
3091}
3092
3093POST(poll)
3094{
3095 if (res > 0) {
3096 UInt i;
3097 struct pollfd * arr = (struct pollfd *)arg1;
3098 for (i = 0; i < arg2; i++)
3099 VG_TRACK( post_mem_write, (Addr)(&arr[i].revents),
3100 sizeof(Short) );
3101 }
3102}
3103
3104PRE(readlink)
3105{
3106 /* int readlink(const char *path, char *buf, size_t bufsiz); */
3107 MAYBE_PRINTF("readlink ( %p, %p, %d )\n", arg1,arg2,arg3);
3108 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "readlink(path)", arg1 );
3109 SYSCALL_TRACK( pre_mem_write, tid, "readlink(buf)", arg2,arg3 );
3110}
3111
3112POST(readlink)
3113{
3114 VG_TRACK( post_mem_write, arg2, res );
3115}
3116
3117PRE(readv)
3118{
3119 /* int readv(int fd, const struct iovec * vector, size_t count); */
3120 Int i;
3121 struct iovec * vec;
3122 MAYBE_PRINTF("readv ( %d, %p, %d )\n",arg1,arg2,arg3);
3123 if (!fd_allowed(arg1, "readv", tid)) {
3124 res = -VKI_EBADF;
3125 } else {
3126 SYSCALL_TRACK( pre_mem_read, tid, "readv(vector)",
3127 arg2, arg3 * sizeof(struct iovec) );
3128 /* ToDo: don't do any of the following if the vector is invalid */
3129 vec = (struct iovec *)arg2;
3130 for (i = 0; i < (Int)arg3; i++)
3131 SYSCALL_TRACK( pre_mem_write, tid, "readv(vector[...])",
3132 (UInt)vec[i].iov_base,vec[i].iov_len );
3133 }
3134}
3135
3136POST(readv)
3137{
3138 if (res > 0) {
3139 Int i;
3140 struct iovec * vec = (struct iovec *)arg2;
3141 Int remains = res;
3142
3143 /* res holds the number of bytes read. */
3144 for (i = 0; i < (Int)arg3; i++) {
3145 Int nReadThisBuf = vec[i].iov_len;
3146 if (nReadThisBuf > remains) nReadThisBuf = remains;
3147 VG_TRACK( post_mem_write, (UInt)vec[i].iov_base, nReadThisBuf );
3148 remains -= nReadThisBuf;
3149 if (remains < 0) VG_(core_panic)("readv: remains < 0");
3150 }
3151 }
3152}
3153
3154PRE(rename)
3155{
3156 /* int rename(const char *oldpath, const char *newpath); */
3157 MAYBE_PRINTF("rename ( %p, %p )\n", arg1, arg2 );
3158 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "rename(oldpath)", arg1 );
3159 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "rename(newpath)", arg2 );
3160}
3161
3162PRE(rmdir)
3163{
3164 /* int rmdir(const char *pathname); */
3165 MAYBE_PRINTF("rmdir ( %p )\n", arg1);
3166 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "rmdir(pathname)", arg1 );
3167}
3168
3169PRE(sched_setparam)
3170{
3171 /* int sched_setparam(pid_t pid, const struct sched_param *p); */
3172 MAYBE_PRINTF("sched_setparam ( %d, %p )\n", arg1, arg2 );
3173 SYSCALL_TRACK( pre_mem_read, tid, "sched_setparam(ptr)",
3174 arg2, sizeof(struct sched_param) );
3175}
3176
3177POST(sched_setparam)
3178{
3179 VG_TRACK( post_mem_write, arg2, sizeof(struct sched_param) );
3180}
3181
3182PRE(sched_getparam)
3183{
3184 /* int sched_getparam(pid_t pid, struct sched_param *p); */
3185 MAYBE_PRINTF("sched_getparam ( %d, %p )\n", arg1, arg2 );
3186 SYSCALL_TRACK( pre_mem_write, tid, "sched_getparam(ptr)",
3187 arg2, sizeof(struct sched_param) );
3188}
3189
3190POST(sched_getparam)
3191{
3192 VG_TRACK( post_mem_write, arg2, sizeof(struct sched_param) );
3193}
3194
3195PRE(sched_yield)
3196{
3197 /* int sched_yield(void); */
3198 MAYBE_PRINTF("sched_yield ()\n" );
3199}
3200
3201PRE(select)
3202{
3203 /* struct sel_arg_struct {
3204 unsigned long n;
3205 fd_set *inp, *outp, *exp;
3206 struct timeval *tvp;
3207 };
3208 int old_select(struct sel_arg_struct *arg);
3209 */
3210 SYSCALL_TRACK( pre_mem_read, tid, "select(args)", arg1, 5*sizeof(UInt) );
3211
3212 {
3213 UInt* arg_struct = (UInt*)arg1;
3214 UInt a1, a2, a3, a4, a5;
3215
3216 a1 = arg_struct[0];
3217 a2 = arg_struct[1];
3218 a3 = arg_struct[2];
3219 a4 = arg_struct[3];
3220 a5 = arg_struct[4];
3221
3222 MAYBE_PRINTF("select ( %d, %p, %p, %p, %p )\n",
3223 a1,a2,a3,a4,a5);
3224 if (a2 != (Addr)NULL)
3225 SYSCALL_TRACK( pre_mem_read, tid, "select(readfds)", a2,
3226 a1/8 /* __FD_SETSIZE/8 */ );
3227 if (a3 != (Addr)NULL)
3228 SYSCALL_TRACK( pre_mem_read, tid, "select(writefds)", a3,
3229 arg1/8 /* __FD_SETSIZE/8 */ );
3230 if (a4 != (Addr)NULL)
3231 SYSCALL_TRACK( pre_mem_read, tid, "select(exceptfds)", a4,
3232 a1/8 /* __FD_SETSIZE/8 */ );
3233 if (a5 != (Addr)NULL)
3234 SYSCALL_TRACK( pre_mem_read, tid, "select(timeout)", a5,
3235 sizeof(struct timeval) );
3236 }
3237}
3238
3239PRE(setitimer)
3240{
3241 /* setitimer(int which, const struct itimerval *value,
3242 struct itimerval *ovalue); */
3243 MAYBE_PRINTF("setitimer ( %d, %p, %p )\n", arg1,arg2,arg3);
3244 if (arg2 != (Addr)NULL)
3245 SYSCALL_TRACK( pre_mem_read,tid, "setitimer(value)",
3246 arg2, sizeof(struct itimerval) );
3247 if (arg3 != (Addr)NULL)
3248 SYSCALL_TRACK( pre_mem_write,tid, "setitimer(ovalue)",
3249 arg3, sizeof(struct itimerval));
3250}
3251
3252POST(setitimer)
3253{
3254 if (arg3 != (Addr)NULL) {
3255 VG_TRACK( post_mem_write,arg3, sizeof(struct itimerval));
3256 }
3257}
3258
3259PRE(setfsgid32)
3260{
3261 /* int setfsgid(uid_t fsgid); */
3262 MAYBE_PRINTF("setfsgid ( %d )\n", arg1);
3263}
3264
3265PRE(setgid)
3266{
3267 /* int setgid(gid_t gid); */
3268 MAYBE_PRINTF("setgid ( %d )\n", arg1);
3269}
3270
3271PREALIAS(setgid32, setgid);
3272
3273PRE(setsid)
3274{
3275 /* pid_t setsid(void); */
3276 MAYBE_PRINTF("setsid ()\n");
3277}
3278
3279PRE(setgroups)
3280{
3281 /* int setgroups(size_t size, const gid_t *list); */
3282 MAYBE_PRINTF("setgroups ( %d, %p )\n", arg1, arg2);
3283 if (arg1 > 0)
3284 SYSCALL_TRACK( pre_mem_read, tid, "setgroups(list)", arg2,
3285 arg1 * sizeof(gid_t) );
3286}
3287
3288PREALIAS(setgroups32, setgroups);
3289
3290PRE(setpgid)
3291{
3292 /* int setpgid(pid_t pid, pid_t pgid); */
3293 MAYBE_PRINTF("setpgid ( %d, %d )\n", arg1, arg2);
3294}
3295
3296POST(setpgid)
3297{
3298 VG_(main_pgrp) = VG_(getpgrp)();
3299}
3300
3301PRE(setregid32)
3302{
3303 /* int setregid(gid_t rgid, gid_t egid); */
3304 MAYBE_PRINTF("setregid32(?) ( %d, %d )\n", arg1, arg2);
3305}
3306
3307PRE(setresuid32)
3308{
3309 /* int setresuid(uid_t ruid, uid_t euid, uid_t suid); */
3310 MAYBE_PRINTF("setresuid32(?) ( %d, %d, %d )\n", arg1, arg2, arg3);
3311}
3312
3313PRE(setreuid)
3314{
3315 /* int setreuid(uid_t ruid, uid_t euid); */
3316 MAYBE_PRINTF("setreuid ( 0x%x, 0x%x )\n", arg1, arg2);
3317}
3318
3319PREALIAS(setreuid32, setreuid);
3320
3321PRE(setrlimit)
3322{
3323 /* int setrlimit (int resource, const struct rlimit *rlim); */
3324 MAYBE_PRINTF("setrlimit ( %d, %p )\n", arg1,arg2);
3325 SYSCALL_TRACK( pre_mem_read, tid, "setrlimit(rlim)",
3326 arg2, sizeof(struct rlimit) );
3327}
3328
3329PRE(setuid)
3330{
3331 /* int setuid(uid_t uid); */
3332 MAYBE_PRINTF("setuid ( %d )\n", arg1);
3333}
3334
3335PREALIAS(setuid32, setuid);
3336
3337PRE(socketcall)
3338{
3339 /* int socketcall(int call, unsigned long *args); */
3340 MAYBE_PRINTF("socketcall ( %d, %p )\n",arg1,arg2);
3341 switch (arg1 /* request */) {
3342
3343 case SYS_SOCKETPAIR:
3344 /* int socketpair(int d, int type, int protocol, int sv[2]); */
3345 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.socketpair(args)",
3346 arg2, 4*sizeof(Addr) );
3347 SYSCALL_TRACK( pre_mem_write, tid, "socketcall.socketpair(sv)",
3348 ((UInt*)arg2)[3], 2*sizeof(int) );
3349 break;
3350
3351 case SYS_SOCKET:
3352 /* int socket(int domain, int type, int protocol); */
3353 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.socket(args)",
3354 arg2, 3*sizeof(Addr) );
3355 break;
3356
3357 case SYS_BIND:
3358 /* int bind(int sockfd, struct sockaddr *my_addr,
3359 int addrlen); */
3360 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.bind(args)",
3361 arg2, 3*sizeof(Addr) );
3362 pre_mem_read_sockaddr( tid, "socketcall.bind(my_addr.%s)",
3363 (struct sockaddr *) (((UInt*)arg2)[1]), ((UInt*)arg2)[2]);
3364 break;
3365
3366 case SYS_LISTEN:
3367 /* int listen(int s, int backlog); */
3368 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.listen(args)",
3369 arg2, 2*sizeof(Addr) );
3370 break;
3371
3372 case SYS_ACCEPT: {
3373 /* int accept(int s, struct sockaddr *addr, int *addrlen); */
3374 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.accept(args)",
3375 arg2, 3*sizeof(Addr) );
3376 {
3377 Addr addr_p = ((UInt*)arg2)[1];
3378 Addr addrlen_p = ((UInt*)arg2)[2];
3379 if (addr_p != (Addr)NULL)
3380 buf_and_len_pre_check ( tid, addr_p, addrlen_p,
3381 "socketcall.accept(addr)",
3382 "socketcall.accept(addrlen_in)" );
3383 }
3384 break;
3385 }
3386
3387 case SYS_SENDTO:
3388 /* int sendto(int s, const void *msg, int len,
3389 unsigned int flags,
3390 const struct sockaddr *to, int tolen); */
3391 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.sendto(args)", arg2,
3392 6*sizeof(Addr) );
3393 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.sendto(msg)",
3394 ((UInt*)arg2)[1], /* msg */
3395 ((UInt*)arg2)[2] /* len */ );
3396 pre_mem_read_sockaddr( tid, "socketcall.sendto(to.%s)",
3397 (struct sockaddr *) (((UInt*)arg2)[4]), ((UInt*)arg2)[5]);
3398 break;
3399
3400 case SYS_SEND:
3401 /* int send(int s, const void *msg, size_t len, int flags); */
3402 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.send(args)", arg2,
3403 4*sizeof(Addr) );
3404 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.send(msg)",
3405 ((UInt*)arg2)[1], /* msg */
3406 ((UInt*)arg2)[2] /* len */ );
3407 break;
3408
3409 case SYS_RECVFROM:
3410 /* int recvfrom(int s, void *buf, int len, unsigned int flags,
3411 struct sockaddr *from, int *fromlen); */
3412 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.recvfrom(args)",
3413 arg2, 6*sizeof(Addr) );
3414 {
3415 Addr buf_p = ((UInt*)arg2)[1];
3416 Int len = ((UInt*)arg2)[2];
3417 Addr from_p = ((UInt*)arg2)[4];
3418 Addr fromlen_p = ((UInt*)arg2)[5];
3419
3420 SYSCALL_TRACK( pre_mem_write, tid, "socketcall.recvfrom(buf)",
3421 buf_p, len );
3422 if (from_p != (Addr)NULL)
3423 buf_and_len_pre_check ( tid, from_p, fromlen_p,
3424 "socketcall.recvfrom(from)",
3425 "socketcall.recvfrom(fromlen_in)" );
3426 }
3427 break;
3428
3429 case SYS_RECV:
3430 /* int recv(int s, void *buf, int len, unsigned int flags); */
3431 /* man 2 recv says:
3432 The recv call is normally used only on a connected socket
3433 (see connect(2)) and is identical to recvfrom with a NULL
3434 from parameter.
3435 */
3436 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.recv(args)",
3437 arg2, 4*sizeof(Addr) );
3438 SYSCALL_TRACK( pre_mem_write, tid, "socketcall.recv(buf)",
3439 ((UInt*)arg2)[1], /* buf */
3440 ((UInt*)arg2)[2] /* len */ );
3441 break;
3442
3443 case SYS_CONNECT:
3444 /* int connect(int sockfd,
3445 struct sockaddr *serv_addr, int addrlen ); */
3446 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.connect(args)",
3447 arg2, 3*sizeof(Addr) );
3448 SYSCALL_TRACK( pre_mem_read, tid,
3449 "socketcall.connect(serv_addr.sa_family)",
3450 ((UInt*)arg2)[1], /* serv_addr */
3451 sizeof (sa_family_t));
3452 pre_mem_read_sockaddr( tid,
3453 "socketcall.connect(serv_addr.%s)",
3454 (struct sockaddr *) (((UInt*)arg2)[1]), ((UInt*)arg2)[2]);
3455 break;
3456
3457 case SYS_SETSOCKOPT:
3458 /* int setsockopt(int s, int level, int optname,
3459 const void *optval, int optlen); */
3460 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.setsockopt(args)",
3461 arg2, 5*sizeof(Addr) );
3462 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.setsockopt(optval)",
3463 ((UInt*)arg2)[3], /* optval */
3464 ((UInt*)arg2)[4] /* optlen */ );
3465 break;
3466
3467 case SYS_GETSOCKOPT:
3468 /* int setsockopt(int s, int level, int optname,
3469 void *optval, socklen_t *optlen); */
3470 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.getsockopt(args)",
3471 arg2, 5*sizeof(Addr) );
3472 {
3473 Addr optval_p = ((UInt*)arg2)[3];
3474 Addr optlen_p = ((UInt*)arg2)[4];
3475 /* vg_assert(sizeof(socklen_t) == sizeof(UInt)); */
3476 if (optval_p != (Addr)NULL)
3477 buf_and_len_pre_check ( tid, optval_p, optlen_p,
3478 "socketcall.getsockopt(optval)",
3479 "socketcall.getsockopt(optlen)" );
3480 }
3481 break;
3482
3483 case SYS_GETSOCKNAME:
3484 /* int getsockname(int s, struct sockaddr* name, int* namelen) */
3485 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.getsockname(args)",
3486 arg2, 3*sizeof(Addr) );
3487 {
3488 Addr name_p = ((UInt*)arg2)[1];
3489 Addr namelen_p = ((UInt*)arg2)[2];
3490
3491 /* Nb: name_p cannot be NULL */
3492 buf_and_len_pre_check ( tid, name_p, namelen_p,
3493 "socketcall.getsockname(name)",
3494 "socketcall.getsockname(namelen_in)" );
3495 }
3496 break;
3497
3498 case SYS_GETPEERNAME:
3499 /* int getpeername(int s, struct sockaddr* name, int* namelen) */
3500 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.getpeername(args)",
3501 arg2, 3*sizeof(Addr) );
3502 {
3503 Addr name_p = ((UInt*)arg2)[1];
3504 Addr namelen_p = ((UInt*)arg2)[2];
3505
3506 /* Nb: name_p cannot be NULL */
3507 buf_and_len_pre_check ( tid, name_p, namelen_p,
3508 "socketcall.getpeername(name)",
3509 "socketcall.getpeername(namelen_in)" );
3510 }
3511 break;
3512
3513 case SYS_SHUTDOWN:
3514 /* int shutdown(int s, int how); */
3515 SYSCALL_TRACK( pre_mem_read, tid, "socketcall.shutdown(args)",
3516 arg2, 2*sizeof(Addr) );
3517 break;
3518
3519 case SYS_SENDMSG: {
3520 /* int sendmsg(int s, const struct msghdr *msg, int flags); */
3521
3522 /* this causes warnings, and I don't get why. glibc bug?
3523 * (after all it's glibc providing the arguments array)
3524 SYSCALL_TRACK( pre_mem_read, "socketcall.sendmsg(args)",
3525 arg2, 3*sizeof(Addr) );
3526 */
3527
3528 struct msghdr *msg = (struct msghdr *)((UInt *)arg2)[ 1 ];
3529 msghdr_foreachfield ( tid, msg, pre_mem_read_sendmsg );
3530
3531 break;
3532 }
3533
3534 case SYS_RECVMSG: {
3535 /* int recvmsg(int s, struct msghdr *msg, int flags); */
3536
3537 /* this causes warnings, and I don't get why. glibc bug?
3538 * (after all it's glibc providing the arguments array)
3539 SYSCALL_TRACK( pre_mem_read, "socketcall.recvmsg(args)",
3540 arg2, 3*sizeof(Addr) );
3541 */
3542
3543 struct msghdr *msg = (struct msghdr *)((UInt *)arg2)[ 1 ];
3544 msghdr_foreachfield ( tid, msg, pre_mem_write_recvmsg );
3545
3546 break;
3547 }
3548
3549 default:
jsgf17059e02003-10-19 16:46:06 +00003550 VG_(message)(Vg_DebugMsg,"Warning: unhandled socketcall 0x%x",arg1);
3551 res = -VKI_EINVAL;
3552 break;
jsgf855d93d2003-10-13 22:26:55 +00003553 }
3554}
3555
3556POST(socketcall)
3557{
3558 /* int socketcall(int call, unsigned long *args); */
3559 MAYBE_PRINTF("socketcall ( %d, %p )\n",arg1,arg2);
3560
3561 switch (arg1 /* request */) {
3562
3563 case SYS_SOCKETPAIR:
3564 /* XXX TODO: check return fd against VG_MAX_FD */
3565 VG_TRACK( post_mem_write, ((UInt*)arg2)[3], 2*sizeof(int) );
3566 break;
3567
3568 case SYS_SOCKET:
3569 if (!fd_allowed(res, "socket", tid)) {
3570 VG_(close)(res);
3571 res = -VKI_EMFILE;
3572 }
3573 break;
3574
3575 case SYS_BIND:
3576 /* int bind(int sockfd, struct sockaddr *my_addr,
3577 int addrlen); */
3578 break;
3579
3580 case SYS_LISTEN:
3581 /* int listen(int s, int backlog); */
3582 break;
3583
3584 case SYS_ACCEPT: {
3585 /* int accept(int s, struct sockaddr *addr, int *addrlen); */
3586 if (!fd_allowed(res, "accept", tid)) {
3587 VG_(close)(res);
3588 res = -VKI_EMFILE;
3589 } else {
3590 Addr addr_p = ((UInt*)arg2)[1];
3591 Addr addrlen_p = ((UInt*)arg2)[2];
3592
3593 if (addr_p != (Addr)NULL)
3594 buf_and_len_post_check ( tid, res, addr_p, addrlen_p,
3595 "socketcall.accept(addrlen_out)" );
3596 }
3597 break;
3598 }
3599
3600 case SYS_SENDTO:
3601 break;
3602
3603 case SYS_SEND:
3604 break;
3605
3606 case SYS_RECVFROM:
3607 {
3608 Addr buf_p = ((UInt*)arg2)[1];
3609 Int len = ((UInt*)arg2)[2];
3610 Addr from_p = ((UInt*)arg2)[4];
3611 Addr fromlen_p = ((UInt*)arg2)[5];
3612
3613 if (from_p != (Addr)NULL)
3614 buf_and_len_post_check ( tid, res, from_p, fromlen_p,
3615 "socketcall.recvfrom(fromlen_out)" );
3616 VG_TRACK( post_mem_write, buf_p, len );
3617 }
3618 break;
3619
3620 case SYS_RECV:
3621 if (res >= 0
3622 && ((UInt*)arg2)[1] != (UInt)NULL) {
3623 VG_TRACK( post_mem_write, ((UInt*)arg2)[1], /* buf */
3624 ((UInt*)arg2)[2] /* len */ );
3625 }
3626 break;
3627
3628 case SYS_CONNECT:
3629 break;
3630
3631 case SYS_SETSOCKOPT:
3632 break;
3633
3634 case SYS_GETSOCKOPT:
3635 {
3636 Addr optval_p = ((UInt*)arg2)[3];
3637 Addr optlen_p = ((UInt*)arg2)[4];
3638
3639 if (optval_p != (Addr)NULL)
3640 buf_and_len_post_check ( tid, res, optval_p, optlen_p,
3641 "socketcall.getsockopt(optlen_out)" );
3642 }
3643 break;
3644
3645 case SYS_GETSOCKNAME:
3646 {
3647 Addr name_p = ((UInt*)arg2)[1];
3648 Addr namelen_p = ((UInt*)arg2)[2];
3649
3650 buf_and_len_post_check ( tid, res, name_p, namelen_p,
3651 "socketcall.getsockname(namelen_out)" );
3652 }
3653 break;
3654
3655 case SYS_GETPEERNAME:
3656 {
3657 Addr name_p = ((UInt*)arg2)[1];
3658 Addr namelen_p = ((UInt*)arg2)[2];
3659
3660 buf_and_len_post_check ( tid, res, name_p, namelen_p,
3661 "socketcall.getpeername(namelen_out)" );
3662 }
3663 break;
3664
3665 case SYS_SHUTDOWN:
3666 break;
3667
3668 case SYS_SENDMSG:
3669 break;
3670
3671 case SYS_RECVMSG:
3672 {
3673 struct msghdr *msg = (struct msghdr *)((UInt *)arg2)[ 1 ];
3674
3675 msghdr_foreachfield( tid, msg, post_mem_write_recvmsg );
3676
3677 break;
3678 }
3679
3680 default:
3681 VG_(message)(Vg_DebugMsg,"FATAL: unhandled socketcall 0x%x",arg1);
3682 VG_(core_panic)("... bye!\n");
3683 break; /*NOTREACHED*/
3684 }
3685}
3686
3687PRE(stat)
3688{
3689 /* int stat(const char *file_name, struct stat *buf); */
3690 MAYBE_PRINTF("stat ( %p, %p )\n",arg1,arg2);
3691 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "stat(file_name)", arg1 );
3692 SYSCALL_TRACK( pre_mem_write, tid, "stat(buf)",
3693 arg2, sizeof(struct stat) );
3694}
3695
3696POST(stat)
3697{
3698 VG_TRACK( post_mem_write, arg2, sizeof(struct stat) );
3699}
3700
3701PRE(statfs)
3702{
3703 /* int statfs(const char *path, struct statfs *buf); */
3704 MAYBE_PRINTF("statfs ( %p, %p )\n",arg1,arg2);
3705 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "statfs(path)", arg1 );
3706 SYSCALL_TRACK( pre_mem_write, tid, "stat(buf)",
3707 arg2, sizeof(struct statfs) );
3708}
3709
3710POST(statfs)
3711{
3712 VG_TRACK( post_mem_write, arg2, sizeof(struct statfs) );
3713}
3714
3715PRE(symlink)
3716{
3717 /* int symlink(const char *oldpath, const char *newpath); */
3718 MAYBE_PRINTF("symlink ( %p, %p )\n",arg1,arg2);
3719 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "symlink(oldpath)", arg1 );
3720 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "symlink(newpath)", arg2 );
3721}
3722
3723PRE(stat64)
3724{
3725 /* int stat64(const char *file_name, struct stat64 *buf); */
3726 MAYBE_PRINTF("stat64 ( %p, %p )\n",arg1,arg2);
3727 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "stat64(file_name)", arg1 );
3728 SYSCALL_TRACK( pre_mem_write, tid, "stat64(buf)",
3729 arg2, sizeof(struct stat64) );
3730}
3731
3732POST(stat64)
3733{
3734 VG_TRACK( post_mem_write, arg2, sizeof(struct stat64) );
3735}
3736
3737PRE(fstat64)
3738{
3739 /* int fstat64(int filedes, struct stat64 *buf); */
3740 MAYBE_PRINTF("fstat64 ( %d, %p )\n",arg1,arg2);
3741 SYSCALL_TRACK( pre_mem_write, tid, "fstat64(buf)",
3742 arg2, sizeof(struct stat64) );
3743}
3744
3745POST(fstat64)
3746{
3747 VG_TRACK( post_mem_write, arg2, sizeof(struct stat64) );
3748}
3749
3750PRE(sysinfo)
3751{
3752 /* int sysinfo(struct sysinfo *info); */
3753 MAYBE_PRINTF("sysinfo ( %p )\n",arg1);
3754 SYSCALL_TRACK( pre_mem_write, tid, "sysinfo(info)",
3755 arg1, sizeof(struct sysinfo) );
3756}
3757
3758POST(sysinfo)
3759{
3760 VG_TRACK( post_mem_write, arg1, sizeof(struct sysinfo) );
3761}
3762
3763PRE(time)
3764{
3765 /* time_t time(time_t *t); */
3766 MAYBE_PRINTF("time ( %p )\n",arg1);
3767 if (arg1 != (UInt)NULL) {
3768 SYSCALL_TRACK( pre_mem_write, tid, "time", arg1, sizeof(time_t) );
3769 }
3770}
3771
3772POST(time)
3773{
3774 if (arg1 != (UInt)NULL) {
3775 VG_TRACK( post_mem_write, arg1, sizeof(time_t) );
3776 }
3777}
3778
3779PRE(times)
3780{
3781 /* clock_t times(struct tms *buf); */
3782 MAYBE_PRINTF("times ( %p )\n",arg1);
3783 SYSCALL_TRACK( pre_mem_write, tid, "times(buf)",
3784 arg1, sizeof(struct tms) );
3785}
3786
3787POST(times)
3788{
3789 if (arg1 != (UInt)NULL) {
3790 VG_TRACK( post_mem_write, arg1, sizeof(struct tms) );
3791 }
3792}
3793
3794PRE(truncate)
3795{
3796 /* int truncate(const char *path, size_t length); */
3797 MAYBE_PRINTF("truncate ( %p, %d )\n", arg1,arg2);
3798 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "truncate(path)", arg1 );
3799}
3800
3801PRE(umask)
3802{
3803 /* mode_t umask(mode_t mask); */
3804 MAYBE_PRINTF("umask ( %d )\n", arg1);
3805}
3806
3807PRE(unlink)
3808{
3809 /* int unlink(const char *pathname) */
3810 MAYBE_PRINTF("ulink ( %p )\n",arg1);
3811 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "unlink(pathname)", arg1 );
3812}
3813
3814PRE(uname)
3815{
3816 /* int uname(struct utsname *buf); */
3817 MAYBE_PRINTF("uname ( %p )\n",arg1);
3818 SYSCALL_TRACK( pre_mem_write, tid, "uname(buf)",
3819 arg1, sizeof(struct utsname) );
3820}
3821
3822POST(uname)
3823{
3824 if (arg1 != (UInt)NULL) {
3825 VG_TRACK( post_mem_write, arg1, sizeof(struct utsname) );
3826 }
3827}
3828
3829PRE(utime)
3830{
3831 /* int utime(const char *filename, struct utimbuf *buf); */
3832 MAYBE_PRINTF("utime ( %p, %p )\n", arg1,arg2);
3833 SYSCALL_TRACK( pre_mem_read_asciiz, tid, "utime(filename)", arg1 );
3834 if (arg2 != (UInt)NULL)
3835 SYSCALL_TRACK( pre_mem_read, tid, "utime(buf)", arg2,
3836 sizeof(struct utimbuf) );
3837}
3838
3839PRE(waitpid)
3840{
3841 /* pid_t waitpid(pid_t pid, int *status, int options); */
3842
3843 MAYBE_PRINTF("waitpid ( %d, %p, %d )\n",
3844 arg1,arg2,arg3);
3845 if (arg2 != (Addr)NULL)
3846 SYSCALL_TRACK( pre_mem_write, tid, "waitpid(status)",
3847 arg2, sizeof(int) );
3848}
3849
3850POST(waitpid)
3851{
3852 if (arg2 != (Addr)NULL)
3853 VG_TRACK( post_mem_write, arg2, sizeof(int) );
3854}
3855
3856PRE(wait4)
3857{
3858 /* pid_t wait4(pid_t pid, int *status, int options,
3859 struct rusage *rusage) */
3860 MAYBE_PRINTF("wait4 ( %d, %p, %d, %p )\n",
3861 arg1,arg2,arg3,arg4);
3862 arg3 &= ~(VKI__WCLONE | VKI__WALL);
3863
3864 if (arg2 != (Addr)NULL)
3865 SYSCALL_TRACK( pre_mem_write, tid, "wait4(status)",
3866 arg2, sizeof(int) );
3867 if (arg4 != (Addr)NULL)
3868 SYSCALL_TRACK( pre_mem_write, tid, "wait4(rusage)", arg4,
3869 sizeof(struct rusage) );
3870}
3871
3872POST(wait4)
3873{
3874 if (arg2 != (Addr)NULL)
3875 VG_TRACK( post_mem_write, arg2, sizeof(int) );
3876 if (arg4 != (Addr)NULL)
3877 VG_TRACK( post_mem_write, arg4, sizeof(struct rusage) );
3878}
3879
3880PRE(writev)
3881{
3882 /* int writev(int fd, const struct iovec * vector, size_t count); */
3883 Int i;
3884 struct iovec * vec;
3885 MAYBE_PRINTF("writev ( %d, %p, %d )\n",arg1,arg2,arg3);
3886 if (!fd_allowed(arg1, "writev", tid)) {
3887 res = -VKI_EBADF;
3888 } else {
3889 SYSCALL_TRACK( pre_mem_read, tid, "writev(vector)",
3890 arg2, arg3 * sizeof(struct iovec) );
3891 /* ToDo: don't do any of the following if the vector is invalid */
3892 vec = (struct iovec *)arg2;
3893 for (i = 0; i < (Int)arg3; i++)
3894 SYSCALL_TRACK( pre_mem_read, tid, "writev(vector[...])",
3895 (UInt)vec[i].iov_base,vec[i].iov_len );
3896 }
3897}
3898
3899PRE(prctl)
3900{
3901 /* int prctl(int option, unsigned long arg2, unsigned long arg3,
3902 unsigned long arg4, unsigned long arg5); */
3903 MAYBE_PRINTF( "prctl ( %d, %d, %d, %d, %d )\n", arg1, arg2, arg3,
3904 arg4, arg5 );
3905}
3906
3907PRE(adjtimex)
3908{
3909 struct timex *tx = (struct timex *)arg1;
3910 MAYBE_PRINTF("adjtimex ( %p )\n", arg1);
3911
3912 SYSCALL_TRACK(pre_mem_read, tid, "adjtimex(timex->modes)", arg1, sizeof(tx->modes));
3913
3914#define ADJX(bit,field) \
3915 if (tx->modes & bit) \
3916 SYSCALL_TRACK(pre_mem_read, tid, \
3917 "adjtimex(timex->"#field")", \
3918 (UInt)&tx->field, sizeof(tx->field))
3919 ADJX(ADJ_FREQUENCY, freq);
3920 ADJX(ADJ_MAXERROR, maxerror);
3921 ADJX(ADJ_ESTERROR, esterror);
3922 ADJX(ADJ_STATUS, status);
3923 ADJX(ADJ_TIMECONST, constant);
3924 ADJX(ADJ_TICK, tick);
3925#undef ADJX
3926
3927 SYSCALL_TRACK(pre_mem_write, tid, "adjtimex(timex)", arg1, sizeof(struct timex));
3928}
3929
3930POST(adjtimex)
3931{
3932 VG_TRACK(post_mem_write, arg1, sizeof(struct timex));
3933}
3934
3935#define SIGNAL_SIMULATION 1
3936
3937PRE(pause)
3938{
3939 /* int pause(void); */
3940 MAYBE_PRINTF("pause ( )\n");
3941}
3942
3943PRE(rt_sigsuspend)
3944{
3945 /* int sigsuspend(const sigset_t *mask); */
3946 MAYBE_PRINTF("sigsuspend ( %p )\n", arg1 );
3947 if (arg1 != (Addr)NULL) {
3948 /* above NULL test is paranoia */
3949 SYSCALL_TRACK( pre_mem_read, tid, "sigsuspend(mask)", arg1,
3950 sizeof(vki_ksigset_t) );
3951 }
3952}
3953
3954PREALIAS(sigsuspend, rt_sigsuspend);
3955
3956PRE(rt_sigtimedwait)
3957{
3958 /* int sigtimedwait(const sigset_t *set, siginfo_t *info,
3959 const struct timespec timeout); */
nethercote9e7e7552003-11-01 14:03:37 +00003960 MAYBE_PRINTF("sigtimedwait ( %p, %p, timeout )\n", arg1, arg2);
3961 if (arg1 != (UInt)NULL)
3962 SYSCALL_TRACK( pre_mem_read, tid, "sigtimedwait(set)", arg1,
3963 sizeof(vki_ksigset_t));
jsgf855d93d2003-10-13 22:26:55 +00003964 if (arg2 != (UInt)NULL)
3965 SYSCALL_TRACK( pre_mem_write, tid, "sigtimedwait(info)", arg2,
3966 sizeof(siginfo_t) );
3967}
3968
3969POST(rt_sigtimedwait)
3970{
3971 if (arg2 != (UInt)NULL)
3972 VG_TRACK( post_mem_write, arg2, sizeof(siginfo_t) );
3973}
3974
3975PRE(rt_sigqueueinfo)
3976{
3977 /* long sys_rt_sigqueueinfo(int pid, int sig, siginfo_t *uinfo) */
3978 MAYBE_PRINTF("rt_sigqueueinfo(%d, %d, %p)\n", arg1, arg2, arg3);
3979 if (arg2 != (UInt)NULL)
3980 SYSCALL_TRACK( pre_mem_read, tid, "sigqueueinfo(uinfo)", arg3,
3981 sizeof(siginfo_t) );
3982}
3983
3984POST(rt_sigqueueinfo)
3985{
3986 if (res >= 0 &&
3987 arg2 != 0 &&
3988 !VG_(is_sig_ign)(arg2) &&
3989 !VG_(ksigismember)(&tst->eff_sig_mask, arg2) &&
3990 arg1 == VG_(getpid)()) {
3991 VG_(proxy_waitsig)();
3992 }
3993}
3994
3995PRE(sigaltstack)
3996{
3997 /* int sigaltstack(const stack_t *ss, stack_t *oss); */
3998 MAYBE_PRINTF("sigaltstack ( %p, %p )\n",arg1,arg2);
3999 if (arg1 != (UInt)NULL) {
4000 SYSCALL_TRACK( pre_mem_read, tid, "sigaltstack(ss)",
4001 arg1, sizeof(vki_kstack_t) );
4002 }
4003 if (arg2 != (UInt)NULL) {
4004 SYSCALL_TRACK( pre_mem_write, tid, "sigaltstack(oss)",
4005 arg2, sizeof(vki_kstack_t) );
4006 }
4007
4008 if (SIGNAL_SIMULATION)
4009 VG_(do__NR_sigaltstack) (tid);
4010}
4011
4012POST(sigaltstack)
4013{
4014 if (res == 0 && arg2 != (UInt)NULL)
4015 VG_TRACK( post_mem_write, arg2, sizeof(vki_kstack_t));
4016}
4017
4018PRE(sigaction)
4019{
4020 /* int sigaction(int signum, struct k_sigaction *act,
4021 struct k_sigaction *oldact); */
4022 MAYBE_PRINTF("sigaction ( %d, %p, %p )\n",arg1,arg2,arg3);
4023 if (arg2 != (UInt)NULL)
4024 SYSCALL_TRACK( pre_mem_read, tid, "sigaction(act)",
4025 arg2, sizeof(vki_ksigaction));
4026 if (arg3 != (UInt)NULL)
4027 SYSCALL_TRACK( pre_mem_write, tid, "sigaction(oldact)",
4028 arg3, sizeof(vki_ksigaction));
4029
4030 if (SIGNAL_SIMULATION)
4031 VG_(do__NR_sigaction)(tid);
4032}
4033
4034POST(sigaction)
4035{
4036 if (res == 0 && arg3 != (UInt)NULL)
4037 VG_TRACK( post_mem_write, arg3, sizeof(vki_ksigaction));
4038}
4039
4040PREALIAS(rt_sigaction, sigaction);
4041POSTALIAS(rt_sigaction, sigaction);
4042
4043PRE(sigprocmask)
4044{
4045 /* int sigprocmask(int how, k_sigset_t *set,
4046 k_sigset_t *oldset); */
4047 MAYBE_PRINTF("sigprocmask ( %d, %p, %p )\n",arg1,arg2,arg3);
4048 if (arg2 != (UInt)NULL)
4049 SYSCALL_TRACK( pre_mem_read, tid, "sigprocmask(set)",
4050 arg2, sizeof(vki_ksigset_t));
4051 if (arg3 != (UInt)NULL)
4052 SYSCALL_TRACK( pre_mem_write, tid, "sigprocmask(oldset)",
4053 arg3, sizeof(vki_ksigset_t));
4054
4055 if (SIGNAL_SIMULATION)
4056 VG_(do__NR_sigprocmask) ( tid,
4057 arg1 /*how*/,
4058 (vki_ksigset_t*) arg2,
4059 (vki_ksigset_t*) arg3 );
4060}
4061
4062POST(sigprocmask)
4063{
4064 if (res == 0 && arg3 != (UInt)NULL)
4065 VG_TRACK( post_mem_write, arg3, sizeof(vki_ksigset_t));
4066}
4067
4068PREALIAS(rt_sigprocmask, sigprocmask);
4069POSTALIAS(rt_sigprocmask, sigprocmask);
4070
4071PRE(sigpending)
4072{
4073 /* int sigpending( sigset_t *set ) ; */
4074 MAYBE_PRINTF( "sigpending ( %p )\n", arg1 );
4075 SYSCALL_TRACK( pre_mem_write, tid, "sigpending(set)",
4076 arg1, sizeof(vki_ksigset_t));
4077}
4078
4079POST(sigpending)
4080{
4081 if ( !VG_( is_kerror )( res ) && res == 0 )
4082 VG_TRACK( post_mem_write, arg1, sizeof( vki_ksigset_t ) ) ;
4083}
4084
4085PREALIAS(rt_sigpending, sigpending);
4086POSTALIAS(rt_sigpending, sigpending);
4087
4088
4089#undef SYSNO
4090#undef res
4091#undef arg1
4092#undef arg2
4093#undef arg3
4094#undef arg4
4095#undef arg5
4096#undef arg6
4097
4098struct sys_info {
4099 Bool may_block; /* is a potentially blocking syscall */
4100 void (*before)(ThreadId tid, ThreadState *tst);
4101 void (*after)(ThreadId tid, ThreadState *tst);
4102};
4103#define SYSB_(name, blk) [__NR_##name] = { blk, before_##name, NULL }
4104#define SYSBA(name, blk) [__NR_##name] = { blk, before_##name, after_##name }
4105
4106static void bad_before(ThreadId tid, ThreadState *tst)
4107{
4108 VG_(message)
4109 (Vg_DebugMsg,"WARNING: unhandled syscall: %d", tst->m_eax);
4110 VG_(message)
4111 (Vg_DebugMsg,"Do not panic. You may be able to fix this easily.");
4112 VG_(message)
4113 (Vg_DebugMsg,"Read the file README_MISSING_SYSCALL_OR_IOCTL.");
4114
4115 tst->m_eax = -VKI_ENOSYS;
4116}
4117
4118static void bad_after(ThreadId tid, ThreadState *tst)
4119{
4120}
4121
4122static const struct sys_info bad_sys = { False, bad_before, bad_after };
4123
4124static const struct sys_info special_sys[] = {
4125 /* special */
4126 SYSB_(exit_group, False),
4127 SYSB_(exit, False),
4128 SYSB_(clone, False),
4129
4130 SYSB_(modify_ldt, False),
4131
fitzhardingee1c06d82003-10-30 07:21:44 +00004132 SYSB_(execve, False),
4133
jsgf855d93d2003-10-13 22:26:55 +00004134#if SIGNAL_SIMULATION
4135 SYSBA(sigaltstack, False),
4136 SYSBA(rt_sigaction, False),
4137 SYSBA(sigaction, False),
4138 SYSBA(rt_sigprocmask, False),
4139 SYSBA(sigprocmask, False),
4140#endif /* SIGNAL_SIMULATION */
4141};
4142#define MAX_SPECIAL_SYS (sizeof(special_sys)/sizeof(special_sys[0]))
4143
4144static const struct sys_info sys_info[] = {
4145 SYSBA(ptrace, False),
4146 SYSB_(mount, True),
4147 SYSB_(umount, False),
4148
4149 SYSB_(setresgid, False),
4150 SYSB_(vhangup, False),
4151 SYSB_(iopl, False),
4152
4153 SYSB_(setxattr, True),
4154 SYSB_(lsetxattr, True),
4155 SYSB_(fsetxattr, True),
4156 SYSBA(getxattr, True),
4157 SYSBA(lgetxattr, True),
4158 SYSBA(fgetxattr, True),
4159 SYSBA(listxattr, True),
4160 SYSBA(llistxattr, True),
4161 SYSBA(flistxattr, True),
4162 SYSB_(removexattr, True),
4163 SYSB_(lremovexattr, True),
4164 SYSB_(fremovexattr, True),
4165
4166 SYSB_(quotactl, False),
4167 SYSBA(lookup_dcookie, False),
4168
4169 SYSB_(truncate64, True),
4170 SYSB_(fdatasync, True),
4171 SYSB_(msync, True),
4172
4173 SYSBA(getpmsg, True),
4174 SYSB_(putpmsg, True),
4175
jsgf855d93d2003-10-13 22:26:55 +00004176 SYSBA(syslog, True),
4177 SYSB_(personality, False),
4178 SYSB_(chroot, False),
4179 SYSB_(madvise, True),
4180 SYSBA(mremap, False),
4181 SYSB_(nice, False),
4182 SYSB_(setresgid32, False),
4183 SYSB_(setfsuid32, False),
4184 SYSBA(_sysctl, False),
4185
4186 SYSB_(sched_getscheduler, False), /* ??? */
4187 SYSB_(sched_setscheduler, False), /* ??? */
4188
4189 SYSB_(mlock, True),
4190 SYSB_(munlock, True),
4191 SYSB_(mlockall, True),
4192 SYSB_(munlockall, True),
4193
4194 SYSB_(sched_get_priority_max, False), /* ??? */
4195 SYSB_(sched_get_priority_min, False), /* ??? */
4196
4197 SYSB_(setpriority, False),
4198 SYSB_(getpriority, False),
4199
4200 SYSB_(setfsgid, False),
4201 SYSB_(setregid, False),
4202 SYSB_(setresuid, False),
4203 SYSB_(setfsuid, False),
4204
4205 SYSBA(sendfile, True),
4206 SYSBA(sendfile64, True),
4207 SYSB_(pwrite64, True),
4208 SYSB_(sync, True),
4209 SYSBA(fstatfs, False),
4210 SYSB_(getsid, False),
4211 SYSBA(pread64, True),
4212 SYSB_(mknod, False),
4213 SYSB_(flock, True),
4214 SYSB_(init_module, True),
4215 SYSB_(ioperm, False),
4216 SYSBA(capget, False),
4217 SYSB_(capset, False),
jsgf855d93d2003-10-13 22:26:55 +00004218 SYSB_(access, False),
4219 SYSBA(brk, False),
4220 SYSB_(chdir, False),
4221 SYSB_(chmod, False),
4222 SYSB_(chown32, False),
4223 SYSB_(lchown32, False),
4224 SYSB_(chown, False),
4225 SYSB_(close, False),
4226 SYSBA(dup, False),
4227 SYSBA(dup2, False),
4228 SYSB_(fcntl, True),
4229 SYSB_(fchdir, False),
4230 SYSB_(fchown32, False),
4231 SYSB_(fchown, False),
4232 SYSB_(fchmod, False),
4233 SYSB_(fcntl64, True),
4234 SYSBA(fstat, False),
4235 SYSBA(fork, False),
4236 SYSB_(fsync, True),
4237 SYSB_(ftruncate, True),
4238 SYSB_(ftruncate64, True),
4239 SYSBA(getdents, True),
4240 SYSBA(getdents64, True),
4241 SYSBA(getgroups32, True),
4242 SYSBA(getgroups, False),
4243 SYSBA(getcwd, False),
4244 SYSB_(geteuid, False),
4245 SYSB_(geteuid32, False),
4246 SYSB_(getegid, False),
4247 SYSB_(getegid32, False),
4248 SYSB_(getgid, False),
4249 SYSB_(getgid32, False),
4250 SYSB_(getpid, False),
4251 SYSB_(getpgid, False),
4252 SYSB_(getpgrp, False),
4253 SYSB_(getppid, False),
4254 SYSBA(getresgid, False),
4255 SYSBA(getresgid32, False),
4256 SYSBA(getresuid, False),
4257 SYSBA(getresuid32, False),
4258 SYSBA(ugetrlimit, False),
4259 SYSBA(getrlimit, False),
4260 SYSBA(getrusage, False),
4261 SYSBA(gettimeofday, False),
4262 SYSB_(getuid, False),
4263 SYSB_(getuid32, False),
4264 SYSBA(ipc, True),
4265 SYSBA(ioctl, True),
4266 SYSBA(kill, False),
4267 SYSB_(link, True),
4268 SYSB_(lseek, False),
4269 SYSBA(_llseek, False),
4270 SYSBA(lstat, False),
4271 SYSBA(lstat64, False),
4272 SYSB_(mkdir, True),
4273 SYSBA(mmap2, False),
4274 SYSBA(mmap, False),
4275 SYSBA(mprotect, False),
4276 SYSBA(munmap, False),
4277 SYSBA(nanosleep, True),
4278 SYSB_(_newselect, True),
4279 SYSBA(open, True),
4280 SYSBA(read, True),
4281 SYSB_(write, True),
4282 SYSBA(creat, True),
4283 SYSBA(pipe, False),
4284 SYSBA(poll, True),
4285 SYSBA(readlink, False),
4286 SYSBA(readv, True),
4287 SYSB_(rename, False),
4288 SYSB_(rmdir, True),
4289 SYSBA(sched_setparam, False), /* ??? */
4290 SYSBA(sched_getparam, False), /* ??? */
4291 SYSB_(sched_yield, False), /* ??? */
4292 SYSB_(select, True),
jsgf855d93d2003-10-13 22:26:55 +00004293 SYSB_(setfsgid32, False),
4294 SYSB_(setgid32, False),
4295 SYSB_(setgid, False),
4296 SYSB_(setsid, False),
4297 SYSB_(setgroups32, False),
4298 SYSB_(setgroups, False),
4299 SYSBA(setpgid, False),
4300 SYSB_(setregid32, False),
4301 SYSB_(setresuid32, False),
4302 SYSB_(setreuid32, False),
4303 SYSB_(setreuid, False),
4304 SYSB_(setrlimit, False),
4305 SYSB_(setuid32, False),
4306 SYSB_(setuid, False),
4307 SYSBA(socketcall, True),
4308 SYSBA(stat, False),
4309 SYSBA(statfs, False),
4310 SYSB_(symlink, True),
4311 SYSBA(stat64, False),
4312 SYSBA(fstat64, False),
4313 SYSBA(sysinfo, False),
4314 SYSBA(time, False),
4315 SYSBA(times, False),
4316 SYSB_(truncate, True),
4317 SYSB_(umask, False),
4318 SYSB_(unlink, True),
4319 SYSBA(uname, False),
4320 SYSB_(utime, True),
4321 SYSBA(waitpid, True),
4322 SYSBA(wait4, True),
4323 SYSB_(writev, True),
4324 SYSB_(prctl, True),
4325 SYSBA(adjtimex, False),
4326
4327 /* new signal handling makes these normal blocking syscalls */
4328 SYSB_(pause, True),
4329 SYSB_(sigsuspend, True),
4330 SYSB_(rt_sigsuspend, True),
4331 SYSBA(rt_sigtimedwait, True),
4332 SYSBA(rt_sigqueueinfo, False),
fitzhardingea09a1b52003-11-07 23:09:48 +00004333
jsgf855d93d2003-10-13 22:26:55 +00004334 SYSBA(sigpending, True), /* not blocking, but must run in LWP context */
4335 SYSBA(rt_sigpending, True), /* not blocking, but must run in LWP context */
4336 SYSB_(alarm, True), /* not blocking, but must run in LWP context */
fitzhardingea09a1b52003-11-07 23:09:48 +00004337 SYSBA(setitimer, True), /* not blocking, but must run in LWP context */
4338 SYSBA(getitimer, True), /* not blocking, but must run in LWP context */
jsgf855d93d2003-10-13 22:26:55 +00004339
4340#if !SIGNAL_SIMULATION
4341 SYSBA(sigaltstack, False),
4342 SYSBA(rt_sigaction, False),
4343 SYSBA(sigaction, False),
4344 SYSBA(rt_sigprocmask, False),
4345 SYSBA(sigprocmask, False),
4346#endif /* !SIGNAL_SIMULATION */
4347};
4348#define MAX_SYS_INFO (sizeof(sys_info)/sizeof(sys_info[0]))
4349
4350#undef SYSB_
4351#undef SYSBA
4352
4353Bool VG_(pre_syscall) ( ThreadId tid )
sewardjde4a1d02002-03-22 01:27:54 +00004354{
sewardj018f7622002-05-15 21:13:39 +00004355 ThreadState* tst;
jsgf855d93d2003-10-13 22:26:55 +00004356 UInt syscallno;
4357 const struct sys_info *sys;
4358 Bool special = False;
4359 Bool syscall_done = False; /* we actually ran the syscall */
sewardjde4a1d02002-03-22 01:27:54 +00004360
njn25e49d8e72002-09-23 09:36:25 +00004361 VGP_PUSHCC(VgpCoreSysWrap);
sewardjde4a1d02002-03-22 01:27:54 +00004362
jsgf855d93d2003-10-13 22:26:55 +00004363 tst = VG_(get_ThreadState)(tid);
sewardj018f7622002-05-15 21:13:39 +00004364
jsgf855d93d2003-10-13 22:26:55 +00004365 /* Convert vfork to fork, since we can't handle it otherwise. */
4366 if (tst->m_eax == __NR_vfork)
4367 tst->m_eax = __NR_fork;
sewardjde4a1d02002-03-22 01:27:54 +00004368
jsgf855d93d2003-10-13 22:26:55 +00004369 syscallno = tst->m_eax;
4370
4371 if (tst->syscallno != -1)
4372 VG_(printf)("tid %d has syscall %d\n", tst->tid, tst->syscallno);
4373
4374 vg_assert(tst->syscallno == -1); /* should be no current syscall */
4375 vg_assert(tst->status == VgTs_Runnable); /* should be runnable */
4376
4377 /* the syscall no is in %eax. For syscalls with <= 6 args,
4378 args 1 .. 6 to the syscall are in %ebx %ecx %edx %esi %edi %ebp.
4379 For calls with > 6 args, %ebx points to a lump of memory
sewardjde4a1d02002-03-22 01:27:54 +00004380 containing the args.
4381
4382 The result is returned in %eax. If this value >= 0, the call
4383 succeeded, and this is the return value. If < 0, it failed, and
4384 the negation of this value is errno. To be more specific,
4385 if res is in the range -EMEDIUMTYPE (-124) .. -EPERM (-1)
4386 (kernel 2.4.9 sources, include/asm-i386/errno.h)
4387 then it indicates an error. Otherwise it doesn't.
4388
4389 Dirk Mueller (mueller@kde.org) says that values -4095 .. -1
4390 (inclusive?) indicate error returns. Not sure where the -4095
4391 comes from.
4392 */
4393
jsgf855d93d2003-10-13 22:26:55 +00004394 /* post_syscall expects us to be "waiting" even if we don't
4395 block */
4396 tst->syscallno = syscallno;
4397 tst->status = VgTs_WaitSys;
sewardjde4a1d02002-03-22 01:27:54 +00004398
jsgf855d93d2003-10-13 22:26:55 +00004399 if (syscallno < MAX_SPECIAL_SYS && special_sys[syscallno].before != NULL) {
4400 sys = &special_sys[syscallno];
4401 special = True;
4402 } else if (syscallno < MAX_SYS_INFO && sys_info[syscallno].before != NULL) {
4403 sys = &sys_info[syscallno];
4404 } else {
4405 sys = &bad_sys;
4406 special = True;
sewardjde4a1d02002-03-22 01:27:54 +00004407 }
4408
jsgf855d93d2003-10-13 22:26:55 +00004409 /* Do any pre-syscall actions */
4410 if (VG_(needs).syscall_wrapper) {
4411 VGP_PUSHCC(VgpSkinSysWrap);
4412 tst->sys_pre_res = SK_(pre_syscall)(tid, syscallno, /*isBlocking*/sys->may_block);
4413 VGP_POPCC(VgpSkinSysWrap);
4414 }
4415
4416 MAYBE_PRINTF("SYSCALL[%d,%d](%3d)%s%s:",
4417 VG_(getpid)(), tid, syscallno,
4418 special ? " special" : "",
4419 sys->may_block ? " blocking" : "");
4420
4421 if (special) {
4422 /* "Special" syscalls are implemented by Valgrind internally,
4423 and do not generate real kernel calls. The expectation,
4424 therefore, is that the "before" function not only does the
4425 appropriate tests, but also performs the syscall itself and
4426 sets the result. Special syscalls cannot block. */
4427 vg_assert(sys->may_block == False);
4428
4429 (sys->before)(tst->tid, tst);
4430
4431 syscall_done = True;
4432 } else {
4433 (sys->before)(tst->tid, tst);
4434
4435 if ((Int)tst->m_eax <= 0) {
4436 /* "before" decided the syscall wasn't viable, so don't do
4437 anything - just pretend the syscall happened. */
4438 syscall_done = True;
4439 } else if (sys->may_block) {
4440 /* issue to worker */
4441 VG_(sys_issue)(tid);
4442 } else {
4443 /* run the syscall directly */
4444 tst->m_eax = VG_(do_syscall)(syscallno,
4445 tst->m_ebx,
4446 tst->m_ecx,
4447 tst->m_edx,
4448 tst->m_esi,
4449 tst->m_edi,
4450 tst->m_ebp);
4451 syscall_done = True;
4452 }
4453 }
4454
4455 VGP_POPCC(VgpCoreSysWrap);
4456
4457 return syscall_done;
4458}
4459
4460
4461void VG_(post_syscall) ( ThreadId tid )
4462{
4463 ThreadState* tst;
4464 UInt syscallno;
4465 const struct sys_info *sys;
4466 Bool special = False;
4467 void *pre_res;
4468
4469 VGP_PUSHCC(VgpCoreSysWrap);
4470
4471 tst = VG_(get_ThreadState)(tid);
4472
4473 /* Tell the skin about the syscall return value */
4474 SET_SYSCALL_RETVAL(tst->tid, tst->m_eax);
4475
4476 syscallno = tst->syscallno;
4477 pre_res = tst->sys_pre_res;
4478
4479 vg_assert(syscallno != -1); /* must be a current syscall */
4480 vg_assert(tst->status == VgTs_WaitSys); /* should be blocked waiting */
4481
4482 if (syscallno < MAX_SPECIAL_SYS && special_sys[syscallno].before != NULL) {
4483 sys = &special_sys[syscallno];
4484 special = True;
4485 } else if (syscallno < MAX_SYS_INFO && sys_info[syscallno].before != NULL) {
4486 sys = &sys_info[syscallno];
4487 } else {
4488 sys = &bad_sys;
4489 special = True;
4490 }
4491
4492 if (!VG_(is_kerror)(tst->m_eax) && sys->after != NULL)
4493 (sys->after)(tst->tid, tst);
sewardjde4a1d02002-03-22 01:27:54 +00004494
njn25e49d8e72002-09-23 09:36:25 +00004495 /* Do any post-syscall actions */
4496 if (VG_(needs).syscall_wrapper) {
4497 VGP_PUSHCC(VgpSkinSysWrap);
jsgf855d93d2003-10-13 22:26:55 +00004498 SK_(post_syscall)(tid, syscallno, pre_res, tst->m_eax, /*isBlocking*/True); // did block
njn25e49d8e72002-09-23 09:36:25 +00004499 VGP_POPCC(VgpSkinSysWrap);
sewardjde4a1d02002-03-22 01:27:54 +00004500 }
4501
fitzhardingee1c06d82003-10-30 07:21:44 +00004502 if (tst->m_eax == -VKI_ERESTARTSYS) {
4503 /* Applications never expect to see this, so we should actually
4504 restart the syscall (it means the signal happened before the
4505 syscall made any progress, so we can safely restart it and
4506 pretend the signal happened before the syscall even
4507 started) */
4508 VG_(restart_syscall)(tid);
4509 }
4510
jsgf855d93d2003-10-13 22:26:55 +00004511 tst->status = VgTs_Runnable; /* runnable again */
4512 tst->syscallno = -1;
sewardj2e93c502002-04-12 11:12:52 +00004513
njn25e49d8e72002-09-23 09:36:25 +00004514 VGP_POPCC(VgpCoreSysWrap);
sewardj2e93c502002-04-12 11:12:52 +00004515}
4516
fitzhardingee1c06d82003-10-30 07:21:44 +00004517void VG_(restart_syscall)(ThreadId tid)
4518{
4519 ThreadState* tst;
4520 tst = VG_(get_ThreadState)(tid);
4521
4522 vg_assert(tst != NULL);
4523 vg_assert(tst->status == VgTs_WaitSys);
4524 vg_assert(tst->syscallno != -1);
4525
4526 tst->m_eax = tst->syscallno;
4527 tst->m_eip -= 2; /* sizeof(int $0x80) */
fitzhardingea09a1b52003-11-07 23:09:48 +00004528
4529 /* Make sure our caller is actually sane, and we're really backing
4530 back over a syscall.
4531
4532 int $0x80 == CD 80
4533 */
4534 {
4535 UChar *p = (UChar *)tst->m_eip;
4536
4537 if (p[0] != 0xcd || p[1] != 0x80)
4538 VG_(message)(Vg_DebugMsg,
4539 "?! restarting over syscall at %p %02x %02x\n",
4540 tst->m_eip, p[0], p[1]);
4541
4542 vg_assert(p[0] == 0xcd && p[1] == 0x80);
4543 }
fitzhardingee1c06d82003-10-30 07:21:44 +00004544}
sewardj2e93c502002-04-12 11:12:52 +00004545
sewardjde4a1d02002-03-22 01:27:54 +00004546/*--------------------------------------------------------------------*/
njn87ef6a62003-08-14 15:23:55 +00004547/*--- end vg_syscalls.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004548/*--------------------------------------------------------------------*/
njnb94b81e2003-09-09 11:27:59 +00004549