blob: 713aef478ff400f4c643260da8a7d76321395978 [file] [log] [blame]
nethercotefd453532004-11-17 17:21:12 +00001
2/*--------------------------------------------------------------------*/
njn2521d322005-05-08 14:45:13 +00003/*--- Linux-specific syscalls, etc. syscalls-linux.c ---*/
nethercotefd453532004-11-17 17:21:12 +00004/*--------------------------------------------------------------------*/
5
6/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
nethercotefd453532004-11-17 17:21:12 +00009
njn53612422005-03-12 16:22:54 +000010 Copyright (C) 2000-2005 Nicholas Nethercote
njn2bc10122005-05-08 02:10:27 +000011 njn@valgrind.org
nethercotefd453532004-11-17 17:21:12 +000012
13 This program is free software; you can redistribute it and/or
14 modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation; either version 2 of the
16 License, or (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful, but
19 WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21 General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
26 02111-1307, USA.
27
28 The GNU General Public License is contained in the file COPYING.
29*/
30
31#include "core.h"
sewardj55f9d1a2005-04-25 11:11:44 +000032#include "pub_core_aspacemgr.h"
sewardjbc22cf72005-06-08 00:02:49 +000033#include "pub_core_libcbase.h"
njn132bfcc2005-06-04 19:16:06 +000034#include "pub_core_libcassert.h"
njneb8896b2005-06-04 20:03:55 +000035#include "pub_core_libcfile.h"
njn36a20fa2005-06-03 03:08:39 +000036#include "pub_core_libcprint.h"
njn43b9a8a2005-05-10 04:37:01 +000037#include "pub_core_tooliface.h"
sewardja8d8e232005-06-07 20:04:56 +000038#include "pub_core_options.h"
sewardjbc22cf72005-06-08 00:02:49 +000039#include "pub_core_signals.h"
sewardja8d8e232005-06-07 20:04:56 +000040
41#include "priv_types_n_macros.h"
sewardjbc22cf72005-06-08 00:02:49 +000042#include "priv_syscalls-generic.h"
sewardja8d8e232005-06-07 20:04:56 +000043#include "priv_syscalls-linux.h"
44
nethercotefd453532004-11-17 17:21:12 +000045/* ---------------------------------------------------------------------
46 PRE/POST wrappers for arch-generic, Linux-specific syscalls
47 ------------------------------------------------------------------ */
48
49// Nb: See the comment above the generic PRE/POST wrappers in
50// coregrind/vg_syscalls.c for notes about how they work.
51
sewardja8d8e232005-06-07 20:04:56 +000052#define PRE(name) DEFN_PRE_TEMPLATE(linux, name)
53#define POST(name) DEFN_POST_TEMPLATE(linux, name)
nethercotefd453532004-11-17 17:21:12 +000054
sewardjbc22cf72005-06-08 00:02:49 +000055PRE(sys_set_tid_address)
56{
57 PRINT("sys_set_tid_address ( %p )", ARG1);
58 PRE_REG_READ1(long, "set_tid_address", int *, tidptr);
59}
60
sewardja8d8e232005-06-07 20:04:56 +000061PRE(sys_exit_group)
sewardjb5f6f512005-03-10 23:59:00 +000062{
sewardja8d8e232005-06-07 20:04:56 +000063 ThreadId t;
64 ThreadState* tst;
sewardjb5f6f512005-03-10 23:59:00 +000065
66 PRINT("exit_group( %d )", ARG1);
67 PRE_REG_READ1(void, "exit_group", int, exit_code);
68
sewardja8d8e232005-06-07 20:04:56 +000069 tst = VG_(get_ThreadState)(tid);
70
sewardjb5f6f512005-03-10 23:59:00 +000071 /* A little complex; find all the threads with the same threadgroup
72 as this one (including this one), and mark them to exit */
73 for (t = 1; t < VG_N_THREADS; t++) {
sewardja8d8e232005-06-07 20:04:56 +000074 if ( /* not alive */
75 VG_(threads)[t].status == VgTs_Empty
76 ||
77 /* not our group */
78 VG_(threads)[t].os_state.threadgroup != tst->os_state.threadgroup
79 )
80 continue;
sewardjb5f6f512005-03-10 23:59:00 +000081
82 VG_(threads)[t].exitreason = VgSrc_ExitSyscall;
83 VG_(threads)[t].os_state.exitcode = ARG1;
84
85 if (t != tid)
86 VG_(kill_thread)(t); /* unblock it, if blocked */
87 }
88
sewardja8d8e232005-06-07 20:04:56 +000089 /* We have to claim the syscall already succeeded. */
90 SET_STATUS_Success(0);
sewardjb5f6f512005-03-10 23:59:00 +000091}
92
sewardja8d8e232005-06-07 20:04:56 +000093PRE(sys_mount)
nethercotefd453532004-11-17 17:21:12 +000094{
95 // Nb: depending on 'flags', the 'type' and 'data' args may be ignored.
96 // We are conservative and check everything, except the memory pointed to
97 // by 'data'.
sewardja8d8e232005-06-07 20:04:56 +000098 *flags |= SfMayBlock;
sewardjb5f6f512005-03-10 23:59:00 +000099 PRINT( "sys_mount( %p, %p, %p, %p, %p )" ,ARG1,ARG2,ARG3,ARG4,ARG5);
nethercotefd453532004-11-17 17:21:12 +0000100 PRE_REG_READ5(long, "mount",
101 char *, source, char *, target, char *, type,
102 unsigned long, flags, void *, data);
njn22cfccb2004-11-27 16:10:23 +0000103 PRE_MEM_RASCIIZ( "mount(source)", ARG1);
104 PRE_MEM_RASCIIZ( "mount(target)", ARG2);
105 PRE_MEM_RASCIIZ( "mount(type)", ARG3);
nethercotefd453532004-11-17 17:21:12 +0000106}
107
sewardja8d8e232005-06-07 20:04:56 +0000108PRE(sys_oldumount)
nethercotefd453532004-11-17 17:21:12 +0000109{
njn22cfccb2004-11-27 16:10:23 +0000110 PRINT("sys_oldumount( %p )", ARG1);
nethercotefd453532004-11-17 17:21:12 +0000111 PRE_REG_READ1(long, "umount", char *, path);
njn22cfccb2004-11-27 16:10:23 +0000112 PRE_MEM_RASCIIZ( "umount(path)", ARG1);
nethercotefd453532004-11-17 17:21:12 +0000113}
114
sewardja8d8e232005-06-07 20:04:56 +0000115PRE(sys_umount)
nethercotefd453532004-11-17 17:21:12 +0000116{
njn22cfccb2004-11-27 16:10:23 +0000117 PRINT("sys_umount( %p )", ARG1);
nethercotefd453532004-11-17 17:21:12 +0000118 PRE_REG_READ2(long, "umount2", char *, path, int, flags);
njn22cfccb2004-11-27 16:10:23 +0000119 PRE_MEM_RASCIIZ( "umount2(path)", ARG1);
nethercotefd453532004-11-17 17:21:12 +0000120}
121
sewardja8d8e232005-06-07 20:04:56 +0000122PRE(sys_llseek)
nethercotefd453532004-11-17 17:21:12 +0000123{
njn22cfccb2004-11-27 16:10:23 +0000124 PRINT("sys_llseek ( %d, 0x%x, 0x%x, %p, %d )", ARG1,ARG2,ARG3,ARG4,ARG5);
nethercotefd453532004-11-17 17:21:12 +0000125 PRE_REG_READ5(long, "llseek",
126 unsigned int, fd, unsigned long, offset_high,
127 unsigned long, offset_low, vki_loff_t *, result,
128 unsigned int, whence);
njn22cfccb2004-11-27 16:10:23 +0000129 PRE_MEM_WRITE( "llseek(result)", ARG4, sizeof(vki_loff_t));
nethercotefd453532004-11-17 17:21:12 +0000130}
131
132POST(sys_llseek)
133{
sewardja8d8e232005-06-07 20:04:56 +0000134 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +0000135 if (RES == 0)
136 POST_MEM_WRITE( ARG4, sizeof(vki_loff_t) );
nethercotefd453532004-11-17 17:21:12 +0000137}
138
sewardja8d8e232005-06-07 20:04:56 +0000139//zz PRE(sys_adjtimex, 0)
140//zz {
141//zz struct vki_timex *tx = (struct vki_timex *)ARG1;
142//zz PRINT("sys_adjtimex ( %p )", ARG1);
143//zz PRE_REG_READ1(long, "adjtimex", struct timex *, buf);
144//zz PRE_MEM_READ( "adjtimex(timex->modes)", ARG1, sizeof(tx->modes));
145//zz
146//zz #define ADJX(bit,field) \
147//zz if (tx->modes & bit) \
148//zz PRE_MEM_READ( "adjtimex(timex->"#field")", \
149//zz (Addr)&tx->field, sizeof(tx->field))
150//zz ADJX(ADJ_FREQUENCY, freq);
151//zz ADJX(ADJ_MAXERROR, maxerror);
152//zz ADJX(ADJ_ESTERROR, esterror);
153//zz ADJX(ADJ_STATUS, status);
154//zz ADJX(ADJ_TIMECONST, constant);
155//zz ADJX(ADJ_TICK, tick);
156//zz #undef ADJX
157//zz
158//zz PRE_MEM_WRITE( "adjtimex(timex)", ARG1, sizeof(struct vki_timex));
159//zz }
160//zz
161//zz POST(sys_adjtimex)
162//zz {
163//zz POST_MEM_WRITE( ARG1, sizeof(struct vki_timex) );
164//zz }
sewardj696c5512005-06-08 23:38:32 +0000165
166PRE(sys_setfsuid16)
167{
168 PRINT("sys_setfsuid16 ( %d )", ARG1);
169 PRE_REG_READ1(long, "setfsuid16", vki_old_uid_t, uid);
170}
171
sewardje6d5e722005-06-10 10:27:55 +0000172PRE(sys_setfsuid)
173{
174 PRINT("sys_setfsuid ( %d )", ARG1);
175 PRE_REG_READ1(long, "setfsuid", vki_uid_t, uid);
176}
sewardj696c5512005-06-08 23:38:32 +0000177
178PRE(sys_setfsgid16)
179{
180 PRINT("sys_setfsgid16 ( %d )", ARG1);
181 PRE_REG_READ1(long, "setfsgid16", vki_old_gid_t, gid);
182}
183
sewardje6d5e722005-06-10 10:27:55 +0000184PRE(sys_setfsgid)
185{
186 PRINT("sys_setfsgid ( %d )", ARG1);
187 PRE_REG_READ1(long, "setfsgid", vki_gid_t, gid);
188}
189
190PRE(sys_setresuid16)
191{
192 PRINT("sys_setresuid16 ( %d, %d, %d )", ARG1, ARG2, ARG3);
193 PRE_REG_READ3(long, "setresuid16",
194 vki_old_uid_t, ruid, vki_old_uid_t, euid, vki_old_uid_t, suid);
195}
196
197PRE(sys_setresuid)
198{
199 PRINT("sys_setresuid ( %d, %d, %d )", ARG1, ARG2, ARG3);
200 PRE_REG_READ3(long, "setresuid",
201 vki_uid_t, ruid, vki_uid_t, euid, vki_uid_t, suid);
202}
203
204PRE(sys_getresuid16)
205{
206 PRINT("sys_getresuid16 ( %p, %p, %p )", ARG1,ARG2,ARG3);
207 PRE_REG_READ3(long, "getresuid16",
208 vki_old_uid_t *, ruid, vki_old_uid_t *, euid,
209 vki_old_uid_t *, suid);
210 PRE_MEM_WRITE( "getresuid16(ruid)", ARG1, sizeof(vki_old_uid_t) );
211 PRE_MEM_WRITE( "getresuid16(euid)", ARG2, sizeof(vki_old_uid_t) );
212 PRE_MEM_WRITE( "getresuid16(suid)", ARG3, sizeof(vki_old_uid_t) );
213}
214POST(sys_getresuid16)
215{
216 vg_assert(SUCCESS);
217 if (RES == 0) {
218 POST_MEM_WRITE( ARG1, sizeof(vki_old_uid_t) );
219 POST_MEM_WRITE( ARG2, sizeof(vki_old_uid_t) );
220 POST_MEM_WRITE( ARG3, sizeof(vki_old_uid_t) );
221 }
222}
sewardj78b50e42005-06-08 01:47:28 +0000223
224PRE(sys_getresuid)
225{
226 PRINT("sys_getresuid ( %p, %p, %p )", ARG1,ARG2,ARG3);
227 PRE_REG_READ3(long, "getresuid",
228 vki_uid_t *, ruid, vki_uid_t *, euid, vki_uid_t *, suid);
229 PRE_MEM_WRITE( "getresuid(ruid)", ARG1, sizeof(vki_uid_t) );
230 PRE_MEM_WRITE( "getresuid(euid)", ARG2, sizeof(vki_uid_t) );
231 PRE_MEM_WRITE( "getresuid(suid)", ARG3, sizeof(vki_uid_t) );
232}
sewardj78b50e42005-06-08 01:47:28 +0000233POST(sys_getresuid)
234{
235 vg_assert(SUCCESS);
236 if (RES == 0) {
237 POST_MEM_WRITE( ARG1, sizeof(vki_uid_t) );
238 POST_MEM_WRITE( ARG2, sizeof(vki_uid_t) );
239 POST_MEM_WRITE( ARG3, sizeof(vki_uid_t) );
240 }
241}
242
sewardje6d5e722005-06-10 10:27:55 +0000243PRE(sys_setresgid16)
244{
245 PRINT("sys_setresgid16 ( %d, %d, %d )", ARG1, ARG2, ARG3);
246 PRE_REG_READ3(long, "setresgid16",
247 vki_old_gid_t, rgid,
248 vki_old_gid_t, egid, vki_old_gid_t, sgid);
249}
250
251PRE(sys_setresgid)
252{
253 PRINT("sys_setresgid ( %d, %d, %d )", ARG1, ARG2, ARG3);
254 PRE_REG_READ3(long, "setresgid",
255 vki_gid_t, rgid, vki_gid_t, egid, vki_gid_t, sgid);
256}
257
258PRE(sys_getresgid16)
259{
260 PRINT("sys_getresgid16 ( %p, %p, %p )", ARG1,ARG2,ARG3);
261 PRE_REG_READ3(long, "getresgid16",
262 vki_old_gid_t *, rgid, vki_old_gid_t *, egid,
263 vki_old_gid_t *, sgid);
264 PRE_MEM_WRITE( "getresgid16(rgid)", ARG1, sizeof(vki_old_gid_t) );
265 PRE_MEM_WRITE( "getresgid16(egid)", ARG2, sizeof(vki_old_gid_t) );
266 PRE_MEM_WRITE( "getresgid16(sgid)", ARG3, sizeof(vki_old_gid_t) );
267}
268POST(sys_getresgid16)
269{
270 vg_assert(SUCCESS);
271 if (RES == 0) {
272 POST_MEM_WRITE( ARG1, sizeof(vki_old_gid_t) );
273 POST_MEM_WRITE( ARG2, sizeof(vki_old_gid_t) );
274 POST_MEM_WRITE( ARG3, sizeof(vki_old_gid_t) );
275 }
276}
sewardj78b50e42005-06-08 01:47:28 +0000277
278PRE(sys_getresgid)
279{
280 PRINT("sys_getresgid ( %p, %p, %p )", ARG1,ARG2,ARG3);
281 PRE_REG_READ3(long, "getresgid",
282 vki_gid_t *, rgid, vki_gid_t *, egid, vki_gid_t *, sgid);
283 PRE_MEM_WRITE( "getresgid(rgid)", ARG1, sizeof(vki_gid_t) );
284 PRE_MEM_WRITE( "getresgid(egid)", ARG2, sizeof(vki_gid_t) );
285 PRE_MEM_WRITE( "getresgid(sgid)", ARG3, sizeof(vki_gid_t) );
286}
287
288POST(sys_getresgid)
289{
290 vg_assert(SUCCESS);
291 if (RES == 0) {
292 POST_MEM_WRITE( ARG1, sizeof(vki_gid_t) );
293 POST_MEM_WRITE( ARG2, sizeof(vki_gid_t) );
294 POST_MEM_WRITE( ARG3, sizeof(vki_gid_t) );
295 }
296}
297
sewardj696c5512005-06-08 23:38:32 +0000298PRE(sys_ioperm)
299{
300 PRINT("sys_ioperm ( %d, %d, %d )", ARG1, ARG2, ARG3 );
301 PRE_REG_READ3(long, "ioperm",
302 unsigned long, from, unsigned long, num, int, turn_on);
303}
304
305PRE(sys_syslog)
306{
307 *flags |= SfMayBlock;
308 PRINT("sys_syslog (%d, %p, %d)", ARG1,ARG2,ARG3);
309 PRE_REG_READ3(long, "syslog", int, type, char *, bufp, int, len);
310 switch (ARG1) {
311 // The kernel uses magic numbers here, rather than named constants,
312 // therefore so do we.
313 case 2: case 3: case 4:
314 PRE_MEM_WRITE( "syslog(bufp)", ARG2, ARG3);
315 break;
316 default:
317 break;
318 }
319}
320
321POST(sys_syslog)
322{
323 switch (ARG1) {
324 case 2: case 3: case 4:
325 POST_MEM_WRITE( ARG2, ARG3 );
326 break;
327 default:
328 break;
329 }
330}
331
332PRE(sys_vhangup)
333{
334 PRINT("sys_vhangup ( )");
335 PRE_REG_READ0(long, "vhangup");
336}
337
338PRE(sys_sysinfo)
339{
340 PRINT("sys_sysinfo ( %p )",ARG1);
341 PRE_REG_READ1(long, "sysinfo", struct sysinfo *, info);
342 PRE_MEM_WRITE( "sysinfo(info)", ARG1, sizeof(struct vki_sysinfo) );
343}
344
345POST(sys_sysinfo)
346{
347 POST_MEM_WRITE( ARG1, sizeof(struct vki_sysinfo) );
348}
349
350PRE(sys_personality)
351{
352 PRINT("sys_personality ( %llu )", (ULong)ARG1);
353 PRE_REG_READ1(long, "personality", vki_u_long, persona);
354}
nethercotefd453532004-11-17 17:21:12 +0000355
sewardja8d8e232005-06-07 20:04:56 +0000356PRE(sys_sysctl)
nethercotefd453532004-11-17 17:21:12 +0000357{
sewardje6d5e722005-06-10 10:27:55 +0000358 struct __vki_sysctl_args *args;
sewardjf308fd82005-03-14 19:52:16 +0000359 PRINT("sys_sysctl ( %p )", ARG1 );
sewardje6d5e722005-06-10 10:27:55 +0000360 args = (struct __vki_sysctl_args *)ARG1;
361 PRE_REG_READ1(long, "sysctl", struct __sysctl_args *, args);
njn22cfccb2004-11-27 16:10:23 +0000362 PRE_MEM_WRITE( "sysctl(args)", ARG1, sizeof(struct __vki_sysctl_args) );
sewardjb5f6f512005-03-10 23:59:00 +0000363 if (!VG_(is_addressable)(ARG1, sizeof(struct __vki_sysctl_args), VKI_PROT_READ)) {
sewardja8d8e232005-06-07 20:04:56 +0000364 SET_STATUS_Failure( VKI_EFAULT );
sewardjb5f6f512005-03-10 23:59:00 +0000365 return;
366 }
367
sewardje6d5e722005-06-10 10:27:55 +0000368 PRE_MEM_READ("sysctl(name)", (Addr)args->name, args->nlen * sizeof(*args->name));
369 if (args->newval != NULL)
370 PRE_MEM_READ("sysctl(newval)", (Addr)args->newval, args->newlen);
371 if (args->oldlenp != NULL) {
372 PRE_MEM_READ("sysctl(oldlenp)", (Addr)args->oldlenp, sizeof(*args->oldlenp));
373 PRE_MEM_WRITE("sysctl(oldval)", (Addr)args->oldval, *args->oldlenp);
sewardjb5f6f512005-03-10 23:59:00 +0000374 }
nethercotefd453532004-11-17 17:21:12 +0000375}
376
377POST(sys_sysctl)
378{
sewardje6d5e722005-06-10 10:27:55 +0000379 struct __vki_sysctl_args *args;
380 args = (struct __vki_sysctl_args *)ARG1;
381 if (args->oldlenp != NULL) {
382 POST_MEM_WRITE((Addr)args->oldlenp, sizeof(*args->oldlenp));
383 POST_MEM_WRITE((Addr)args->oldval, 1 + *args->oldlenp);
sewardjb5f6f512005-03-10 23:59:00 +0000384 }
nethercotefd453532004-11-17 17:21:12 +0000385}
386
sewardje6d5e722005-06-10 10:27:55 +0000387PRE(sys_prctl)
388{
389 *flags |= SfMayBlock;
390 PRINT( "prctl ( %d, %d, %d, %d, %d )", ARG1, ARG2, ARG3, ARG4, ARG5 );
391 // XXX: too simplistic, often not all args are used
392 // Nb: can't use "ARG2".."ARG5" here because that's our own macro...
393 PRE_REG_READ5(long, "prctl",
394 int, option, unsigned long, arg2, unsigned long, arg3,
395 unsigned long, arg4, unsigned long, arg5);
396 // XXX: totally wrong... we need to look at the 'option' arg, and do
397 // PRE_MEM_READs/PRE_MEM_WRITEs as necessary...
398}
399
400PRE(sys_sendfile)
401{
402 *flags |= SfMayBlock;
403 PRINT("sys_sendfile ( %d, %d, %p, %llu )", ARG1,ARG2,ARG3,(ULong)ARG4);
404 PRE_REG_READ4(ssize_t, "sendfile",
405 int, out_fd, int, in_fd, vki_off_t *, offset,
406 vki_size_t, count);
407 if (ARG3 != 0)
408 PRE_MEM_WRITE( "sendfile(offset)", ARG3, sizeof(vki_off_t) );
409}
410POST(sys_sendfile)
411{
412 if (ARG3 != 0 ) {
413 POST_MEM_WRITE( ARG3, sizeof( vki_off_t ) );
414 }
415}
416
417PRE(sys_sendfile64)
418{
419 *flags |= SfMayBlock;
420 PRINT("sendfile64 ( %d, %d, %p, %llu )",ARG1,ARG2,ARG3,(ULong)ARG4);
421 PRE_REG_READ4(ssize_t, "sendfile64",
422 int, out_fd, int, in_fd, vki_loff_t *, offset,
423 vki_size_t, count);
424 if (ARG3 != 0)
425 PRE_MEM_WRITE( "sendfile64(offset)", ARG3, sizeof(vki_loff_t) );
426}
427POST(sys_sendfile64)
428{
429 if (ARG3 != 0 ) {
430 POST_MEM_WRITE( ARG3, sizeof(vki_loff_t) );
431 }
432}
sewardjbc22cf72005-06-08 00:02:49 +0000433
434PRE(sys_futex)
435{
436 /*
437 arg param used by ops
438
439 ARG1 - u32 *futex all
440 ARG2 - int op
441 ARG3 - int val WAIT,WAKE,FD,REQUEUE,CMP_REQUEUE
442 ARG4 - struct timespec *utime WAIT:time* REQUEUE,CMP_REQUEUE:val2
443 ARG5 - u32 *uaddr2 REQUEUE,CMP_REQUEUE
444 ARG6 - int val3 CMP_REQUEUE
445 */
446 PRINT("sys_futex ( %p, %d, %d, %p, %p )", ARG1,ARG2,ARG3,ARG4,ARG5);
447 PRE_REG_READ6(long, "futex",
448 vki_u32 *, futex, int, op, int, val,
449 struct timespec *, utime, vki_u32 *, uaddr2, int, val3);
450
451 PRE_MEM_READ( "futex(futex)", ARG1, sizeof(Int) );
452
453 *flags |= SfMayBlock;
454
455 switch(ARG2) {
456 case VKI_FUTEX_WAIT:
457 if (ARG4 != 0)
458 PRE_MEM_READ( "futex(timeout)", ARG4, sizeof(struct vki_timespec) );
459 break;
460
461 case VKI_FUTEX_REQUEUE:
462 case VKI_FUTEX_CMP_REQUEUE:
463 PRE_MEM_READ( "futex(futex2)", ARG5, sizeof(Int) );
464 break;
465
466 case VKI_FUTEX_WAKE:
467 case VKI_FUTEX_FD:
468 /* no additional pointers */
469 break;
470
471 default:
472 SET_STATUS_Failure( VKI_ENOSYS ); // some futex function we don't understand
473 break;
474 }
475}
476
477POST(sys_futex)
478{
479 vg_assert(SUCCESS);
480 POST_MEM_WRITE( ARG1, sizeof(int) );
481 if (ARG2 == VKI_FUTEX_FD) {
482 if (!VG_(fd_allowed)(RES, "futex", tid, True)) {
483 VG_(close)(RES);
484 SET_STATUS_Failure( VKI_EMFILE );
485 } else {
486 if (VG_(clo_track_fds))
487 VG_(record_fd_open)(tid, RES, VG_(arena_strdup)(VG_AR_CORE, (Char*)ARG1));
488 }
489 }
490}
491
sewardje6d5e722005-06-10 10:27:55 +0000492PRE(sys_epoll_create)
493{
494 PRINT("sys_epoll_create ( %d )", ARG1);
495 PRE_REG_READ1(long, "epoll_create", int, size);
496}
497POST(sys_epoll_create)
498{
499 vg_assert(SUCCESS);
500 if (!VG_(fd_allowed)(RES, "epoll_create", tid, True)) {
501 VG_(close)(RES);
502 SET_STATUS_Failure( VKI_EMFILE );
503 } else {
504 if (VG_(clo_track_fds))
505 VG_(record_fd_open) (tid, RES, NULL);
506 }
507}
508
509PRE(sys_epoll_ctl)
510{
511 static const HChar* epoll_ctl_s[3] = {
512 "EPOLL_CTL_ADD",
513 "EPOLL_CTL_DEL",
514 "EPOLL_CTL_MOD"
515 };
516 PRINT("sys_epoll_ctl ( %d, %s, %d, %p )",
517 ARG1, ( ARG2<3 ? epoll_ctl_s[ARG2] : "?" ), ARG3, ARG4);
518 PRE_REG_READ4(long, "epoll_ctl",
519 int, epfd, int, op, int, fd, struct epoll_event *, event);
520 PRE_MEM_READ( "epoll_ctl(event)", ARG4, sizeof(struct epoll_event) );
521}
522
523PRE(sys_epoll_wait)
524{
525 *flags |= SfMayBlock;
526 PRINT("sys_epoll_wait ( %d, %p, %d, %d )", ARG1, ARG2, ARG3, ARG4);
527 PRE_REG_READ4(long, "epoll_wait",
528 int, epfd, struct epoll_event *, events,
529 int, maxevents, int, timeout);
530 PRE_MEM_WRITE( "epoll_wait(events)", ARG2, sizeof(struct epoll_event)*ARG3);
531}
532POST(sys_epoll_wait)
533{
534 vg_assert(SUCCESS);
535 if (RES > 0)
536 POST_MEM_WRITE( ARG2, sizeof(struct epoll_event)*RES ) ;
537}
sewardj8c257322005-06-08 01:01:48 +0000538
539PRE(sys_gettid)
540{
541 PRINT("sys_gettid ()");
542 PRE_REG_READ0(long, "gettid");
543}
544
sewardja8d8e232005-06-07 20:04:56 +0000545//zz PRE(sys_tkill, Special)
546//zz {
547//zz /* int tkill(pid_t tid, int sig); */
548//zz PRINT("sys_tkill ( %d, %d )", ARG1,ARG2);
549//zz PRE_REG_READ2(long, "tkill", int, tid, int, sig);
550//zz if (!VG_(client_signal_OK)(ARG2)) {
sewardjbc22cf72005-06-08 00:02:49 +0000551//zz SET_STATUS_( -VKI_EINVAL );
sewardja8d8e232005-06-07 20:04:56 +0000552//zz return;
553//zz }
554//zz
555//zz /* If we're sending SIGKILL, check to see if the target is one of
556//zz our threads and handle it specially. */
557//zz if (ARG2 == VKI_SIGKILL && VG_(do_sigkill)(ARG1, -1))
sewardjbc22cf72005-06-08 00:02:49 +0000558//zz SET_STATUS_(0);
sewardja8d8e232005-06-07 20:04:56 +0000559//zz else
sewardjbc22cf72005-06-08 00:02:49 +0000560//zz SET_STATUS_(VG_(do_syscall2)(SYSNO, ARG1, ARG2));
sewardja8d8e232005-06-07 20:04:56 +0000561//zz
562//zz if (VG_(clo_trace_signals))
563//zz VG_(message)(Vg_DebugMsg, "tkill: sent signal %d to pid %d",
564//zz ARG2, ARG1);
565//zz // Check to see if this kill gave us a pending signal
566//zz XXX FIXME VG_(poll_signals)(tid);
567//zz }
sewardjbc22cf72005-06-08 00:02:49 +0000568
569PRE(sys_tgkill)
570{
571 /* int tgkill(pid_t tgid, pid_t tid, int sig); */
572 PRINT("sys_tgkill ( %d, %d, %d )", ARG1,ARG2,ARG3);
573 PRE_REG_READ3(long, "tgkill", int, tgid, int, tid, int, sig);
574 if (!VG_(client_signal_OK)(ARG3)) {
575 SET_STATUS_Failure( VKI_EINVAL );
576 return;
577 }
578
579 /* If we're sending SIGKILL, check to see if the target is one of
580 our threads and handle it specially. */
581 if (ARG3 == VKI_SIGKILL && VG_(do_sigkill)(ARG2, ARG1))
582 SET_STATUS_Success(0);
583 else
584 SET_STATUS_from_SysRes(VG_(do_syscall3)(SYSNO, ARG1, ARG2, ARG3));
585
586 if (VG_(clo_trace_signals))
587 VG_(message)(Vg_DebugMsg, "tgkill: sent signal %d to pid %d/%d",
588 ARG3, ARG1, ARG2);
589 /* Check to see if this kill gave us a pending signal */
590 *flags |= SfPollAfter;
591}
592
593POST(sys_tgkill)
594{
595 if (VG_(clo_trace_signals))
596 VG_(message)(Vg_DebugMsg, "tgkill: sent signal %d to pid %d/%d",
597 ARG3, ARG1, ARG2);
598}
599
sewardja8d8e232005-06-07 20:04:56 +0000600//zz PRE(sys_fadvise64, 0)
601//zz {
602//zz PRINT("sys_fadvise64 ( %d, %lld, %lu, %d )", ARG1,ARG2,ARG3);
603//zz PRE_REG_READ4(long, "fadvise64",
604//zz int, fd, vki_loff_t, offset, vki_size_t, len, int, advice)
605//zz }
606//zz
607//zz PRE(sys_fadvise64_64, 0)
608//zz {
609//zz PRINT("sys_fadvise64_64 ( %d, %lld, %lld, %d )", ARG1,ARG2,ARG3);
610//zz PRE_REG_READ4(long, "fadvise64_64",
611//zz int, fd, vki_loff_t, offset, vki_loff_t, len, int, advice)
612//zz }
sewardje6d5e722005-06-10 10:27:55 +0000613
614// Nb: this wrapper has to pad/unpad memory around the syscall itself,
615// and this allows us to control exactly the code that gets run while
616// the padding is in place.
617PRE(sys_io_setup)
618{
619 SizeT size;
620 Addr addr;
621
622 PRINT("sys_io_setup ( %u, %p )", ARG1,ARG2);
623 PRE_REG_READ2(long, "io_setup",
624 unsigned, nr_events, vki_aio_context_t *, ctxp);
625 PRE_MEM_WRITE( "io_setup(ctxp)", ARG2, sizeof(vki_aio_context_t) );
626
627 size = VG_PGROUNDUP(sizeof(struct vki_aio_ring) +
628 ARG1*sizeof(struct vki_io_event));
629 addr = VG_(find_map_space)(0, size, True);
630
631 if (addr == 0) {
632 SET_STATUS_Failure( VKI_ENOMEM );
633 return;
634 }
635
636 VG_(map_segment)(addr, size, VKI_PROT_READ|VKI_PROT_WRITE, SF_FIXED);
637
638 VG_(pad_address_space)(0);
639 SET_STATUS_from_SysRes( VG_(do_syscall2)(SYSNO, ARG1, ARG2) );
640 VG_(unpad_address_space)(0);
641
642 if (SUCCESS && RES == 0) {
643 struct vki_aio_ring *r = *(struct vki_aio_ring **)ARG2;
644
645 vg_assert(addr == (Addr)r);
646 vg_assert(VG_(valid_client_addr)(addr, size, tid, "io_setup"));
647
648 VG_TRACK( new_mem_mmap, addr, size, True, True, False );
649 POST_MEM_WRITE( ARG2, sizeof(vki_aio_context_t) );
650 }
651 else {
652 VG_(unmap_range)(addr, size);
653 }
654}
655
656// Nb: This wrapper is "Special" because we need 'size' to do the unmap
657// after the syscall. We must get 'size' from the aio_ring structure,
658// before the syscall, while the aio_ring structure still exists. (And we
659// know that we must look at the aio_ring structure because Tom inspected the
660// kernel and glibc sources to see what they do, yuk.)
661//
662// XXX This segment can be implicitly unmapped when aio
663// file-descriptors are closed...
664PRE(sys_io_destroy)
665{
666 Segment *s = VG_(find_segment)(ARG1);
667 struct vki_aio_ring *r;
668 SizeT size;
669
670 PRINT("sys_io_destroy ( %llu )", (ULong)ARG1);
671 PRE_REG_READ1(long, "io_destroy", vki_aio_context_t, ctx);
672
673 // If we are going to seg fault (due to a bogus ARG1) do it as late as
674 // possible...
675 r = *(struct vki_aio_ring **)ARG1;
676 size = VG_PGROUNDUP(sizeof(struct vki_aio_ring) +
677 r->nr*sizeof(struct vki_io_event));
678
679 SET_STATUS_from_SysRes( VG_(do_syscall1)(SYSNO, ARG1) );
680
681 if (SUCCESS && RES == 0 && s != NULL) {
682 VG_TRACK( die_mem_munmap, ARG1, size );
683 VG_(unmap_range)(ARG1, size);
684 }
685}
686
687PRE(sys_io_getevents)
688{
689 *flags |= SfMayBlock;
690 PRINT("sys_io_getevents ( %llu, %lld, %lld, %p, %p )",
691 (ULong)ARG1,(Long)ARG2,(Long)ARG3,ARG4,ARG5);
692 PRE_REG_READ5(long, "io_getevents",
693 vki_aio_context_t, ctx_id, long, min_nr, long, nr,
694 struct io_event *, events,
695 struct timespec *, timeout);
696 if (ARG3 > 0)
697 PRE_MEM_WRITE( "io_getevents(events)",
698 ARG4, sizeof(struct vki_io_event)*ARG3 );
699 if (ARG5 != 0)
700 PRE_MEM_READ( "io_getevents(timeout)",
701 ARG5, sizeof(struct vki_timespec));
702}
703POST(sys_io_getevents)
704{
705 Int i;
706 vg_assert(SUCCESS);
707 if (RES > 0) {
708 POST_MEM_WRITE( ARG4, sizeof(struct vki_io_event)*RES );
709 for (i = 0; i < RES; i++) {
710 const struct vki_io_event *vev = ((struct vki_io_event *)ARG4) + i;
711 const struct vki_iocb *cb = (struct vki_iocb *)(Addr)vev->obj;
712
713 switch (cb->aio_lio_opcode) {
714 case VKI_IOCB_CMD_PREAD:
715 if (vev->result > 0)
716 POST_MEM_WRITE( cb->aio_buf, vev->result );
717 break;
718
719 case VKI_IOCB_CMD_PWRITE:
720 break;
721
722 default:
723 VG_(message)(Vg_DebugMsg,
724 "Warning: unhandled io_getevents opcode: %u\n",
725 cb->aio_lio_opcode);
726 break;
727 }
728 }
729 }
730}
731
732PRE(sys_io_submit)
733{
734 Int i;
735
736 PRINT("sys_io_submit( %llu, %lld, %p )", (ULong)ARG1,(Long)ARG2,ARG3);
737 PRE_REG_READ3(long, "io_submit",
738 vki_aio_context_t, ctx_id, long, nr,
739 struct iocb **, iocbpp);
740 PRE_MEM_READ( "io_submit(iocbpp)", ARG3, ARG2*sizeof(struct vki_iocb *) );
741 if (ARG3 != 0) {
742 for (i = 0; i < ARG2; i++) {
743 struct vki_iocb *cb = ((struct vki_iocb **)ARG3)[i];
744 PRE_MEM_READ( "io_submit(iocb)", (Addr)cb, sizeof(struct vki_iocb) );
745 switch (cb->aio_lio_opcode) {
746 case VKI_IOCB_CMD_PREAD:
747 PRE_MEM_WRITE( "io_submit(PREAD)", cb->aio_buf, cb->aio_nbytes );
748 break;
749
750 case VKI_IOCB_CMD_PWRITE:
751 PRE_MEM_READ( "io_submit(PWRITE)", cb->aio_buf, cb->aio_nbytes );
752 break;
753
754 default:
755 VG_(message)(Vg_DebugMsg,"Warning: unhandled io_submit opcode: %u\n",
756 cb->aio_lio_opcode);
757 break;
758 }
759 }
760 }
761}
762
763PRE(sys_io_cancel)
764{
765 PRINT("sys_io_cancel( %llu, %p, %p )", (ULong)ARG1,ARG2,ARG3);
766 PRE_REG_READ3(long, "io_cancel",
767 vki_aio_context_t, ctx_id, struct iocb *, iocb,
768 struct io_event *, result);
769 PRE_MEM_READ( "io_cancel(iocb)", ARG2, sizeof(struct vki_iocb) );
770 PRE_MEM_WRITE( "io_cancel(result)", ARG3, sizeof(struct vki_io_event) );
771}
772
773POST(sys_io_cancel)
774{
775 POST_MEM_WRITE( ARG3, sizeof(struct vki_io_event) );
776}
777
778#undef PRE
779#undef POST
nethercotefd453532004-11-17 17:21:12 +0000780
781/*--------------------------------------------------------------------*/
782/*--- end ---*/
783/*--------------------------------------------------------------------*/