blob: fbaaba9c867d18a864cc1a19f9c3d86dedf66e5e [file] [log] [blame]
sewardjde4a1d02002-03-22 01:27:54 +00001
2/*--------------------------------------------------------------------*/
njnc1b01812005-06-17 22:19:06 +00003/*--- Wrappers for generic Unix system calls syswrap-generic.c ---*/
sewardjde4a1d02002-03-22 01:27:54 +00004/*--------------------------------------------------------------------*/
5
6/*
njnb9c427c2004-12-01 14:14:42 +00007 This file is part of Valgrind, a dynamic binary instrumentation
8 framework.
sewardjde4a1d02002-03-22 01:27:54 +00009
njn53612422005-03-12 16:22:54 +000010 Copyright (C) 2000-2005 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
njnc7561b92005-06-19 01:24:32 +000031#include "pub_core_basics.h"
32#include "pub_core_threadstate.h"
sewardj45f4e7c2005-09-27 19:20:21 +000033#include "pub_core_debuginfo.h" // VG_(di_notify_*)
sewardj55f9d1a2005-04-25 11:11:44 +000034#include "pub_core_aspacemgr.h"
sewardj45f4e7c2005-09-27 19:20:21 +000035#include "pub_core_transtab.h" // VG_(discard_translations)
36#include "pub_core_clientstate.h" // VG_(brk_base), VG_(brk_limit)
njn899ce732005-06-21 00:28:11 +000037#include "pub_core_debuglog.h"
njn0087c502005-07-01 04:15:36 +000038#include "pub_core_errormgr.h"
njn97405b22005-06-02 03:39:33 +000039#include "pub_core_libcbase.h"
sewardja8d8e232005-06-07 20:04:56 +000040#include "pub_core_libcassert.h"
njnde62cbf2005-06-10 22:08:14 +000041#include "pub_core_libcfile.h"
42#include "pub_core_libcprint.h"
njnf39e9a32005-06-12 02:43:17 +000043#include "pub_core_libcproc.h"
njnde62cbf2005-06-10 22:08:14 +000044#include "pub_core_libcsignal.h"
njnaf1d7df2005-06-11 01:31:52 +000045#include "pub_core_mallocfree.h"
sewardja8d8e232005-06-07 20:04:56 +000046#include "pub_core_options.h"
njnc7561b92005-06-19 01:24:32 +000047#include "pub_core_scheduler.h"
sewardja8d8e232005-06-07 20:04:56 +000048#include "pub_core_signals.h"
njn419bbcb2005-06-21 03:52:49 +000049#include "pub_core_stacktrace.h" // For VG_(get_and_pp_StackTrace)()
njn9abd6082005-06-17 21:31:45 +000050#include "pub_core_syscall.h"
njnc1b01812005-06-17 22:19:06 +000051#include "pub_core_syswrap.h"
njn419bbcb2005-06-21 03:52:49 +000052#include "pub_core_tooliface.h"
njn73750612005-10-14 03:11:30 +000053#include "pub_core_ume.h"
sewardj55f9d1a2005-04-25 11:11:44 +000054
sewardja8d8e232005-06-07 20:04:56 +000055#include "priv_types_n_macros.h"
njnc1b01812005-06-17 22:19:06 +000056#include "priv_syswrap-generic.h"
sewardjde4a1d02002-03-22 01:27:54 +000057
sewardja8d8e232005-06-07 20:04:56 +000058#include "vki_unistd.h" /* for the __NR_* constants */
sewardjde4a1d02002-03-22 01:27:54 +000059
jsgf855d93d2003-10-13 22:26:55 +000060
sewardj45f4e7c2005-09-27 19:20:21 +000061/* Returns True iff address range is something the client can
62 plausibly mess with: all of it is either already belongs to the
63 client or is free or a reservation. */
64
sewardj7eb7c582005-06-23 01:02:53 +000065Bool ML_(valid_client_addr)(Addr start, SizeT size, ThreadId tid,
nethercote8ff888f2004-11-17 17:11:45 +000066 const Char *syscallname)
fitzhardinge1a303042003-12-22 08:48:50 +000067{
fitzhardinge1a303042003-12-22 08:48:50 +000068 Bool ret;
69
70 if (size == 0)
71 return True;
72
sewardj45f4e7c2005-09-27 19:20:21 +000073 ret = VG_(am_is_valid_for_client_or_free_or_resvn)
74 (start,size,VKI_PROT_NONE);
fitzhardinge1a303042003-12-22 08:48:50 +000075
76 if (0)
sewardj45f4e7c2005-09-27 19:20:21 +000077 VG_(printf)("%s: test=%p-%p ret=%d\n",
78 syscallname, start, start+size-1, (Int)ret);
fitzhardinge1a303042003-12-22 08:48:50 +000079
nethercote1543adf2004-10-25 15:43:21 +000080 if (!ret && syscallname != NULL) {
sewardja8d8e232005-06-07 20:04:56 +000081 VG_(message)(Vg_UserMsg, "Warning: client syscall %s tried "
82 "to modify addresses %p-%p",
sewardj45f4e7c2005-09-27 19:20:21 +000083 syscallname, start, start+size-1);
fitzhardinge1a303042003-12-22 08:48:50 +000084 if (VG_(clo_verbosity) > 1) {
njnd01fef72005-03-25 23:35:48 +000085 VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
fitzhardinge1a303042003-12-22 08:48:50 +000086 }
87 }
88
89 return ret;
90}
91
sewardj45f4e7c2005-09-27 19:20:21 +000092
sewardj7eb7c582005-06-23 01:02:53 +000093Bool ML_(client_signal_OK)(Int sigNo)
njn419bbcb2005-06-21 03:52:49 +000094{
95 /* signal 0 is OK for kill */
njn351d0062005-06-21 22:23:59 +000096 Bool ret = sigNo >= 0 && sigNo <= VG_SIGVGRTUSERMAX;
njn419bbcb2005-06-21 03:52:49 +000097
98 //VG_(printf)("client_signal_OK(%d) -> %d\n", sigNo, ret);
99
100 return ret;
101}
102
sewardj45f4e7c2005-09-27 19:20:21 +0000103
104/* Handy small function to help stop wrappers from segfaulting when
105 presented with bogus client addresses. Is not used for generating
106 user-visible errors. */
107
108Bool ML_(safe_to_deref) ( void* start, SizeT size )
109{
110 return VG_(am_is_valid_for_client)( (Addr)start, size, VKI_PROT_NONE );
111}
112
113
njn25e49d8e72002-09-23 09:36:25 +0000114/* ---------------------------------------------------------------------
nethercote27ea8bc2004-07-10 17:21:14 +0000115 Doing mmap, mremap
njn25e49d8e72002-09-23 09:36:25 +0000116 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000117
njn25e49d8e72002-09-23 09:36:25 +0000118// Nb: this isn't done as precisely as possible, but it seems that programs
119// are usually sufficiently well-behaved that the more obscure corner cases
120// aren't important. Various comments in the few functions below give more
121// details... njn 2002-Sep-17
122
123/* AFAICT from kernel sources (mm/mprotect.c) and general experimentation,
124 munmap, mprotect (and mremap??) work at the page level. So addresses
125 and lengths must be adjusted for this. */
126
127/* Mash around start and length so that the area exactly covers
128 an integral number of pages. If we don't do that, memcheck's
129 idea of addressible memory diverges from that of the
130 kernel's, which causes the leak detector to crash. */
131static
sewardj45f4e7c2005-09-27 19:20:21 +0000132void page_align_addr_and_len( Addr* a, SizeT* len)
sewardjde4a1d02002-03-22 01:27:54 +0000133{
fitzhardinge98abfc72003-12-16 02:05:15 +0000134 Addr ra;
135
njn13bfd852005-06-02 03:52:53 +0000136 ra = VG_PGROUNDDN(*a);
137 *len = VG_PGROUNDUP(*a + *len) - ra;
fitzhardinge98abfc72003-12-16 02:05:15 +0000138 *a = ra;
sewardjde4a1d02002-03-22 01:27:54 +0000139}
140
sewardj45f4e7c2005-09-27 19:20:21 +0000141/* When a client mmap has been successfully done, this function must
142 be called. It notifies both aspacem and the tool of the new
143 mapping.
144*/
145void
146ML_(notify_aspacem_and_tool_of_mmap) ( Addr a, SizeT len, UInt prot,
sewardj274461d2005-10-02 17:01:41 +0000147 UInt flags, Int fd, Off64T offset )
sewardjde4a1d02002-03-22 01:27:54 +0000148{
sewardj45f4e7c2005-09-27 19:20:21 +0000149 Bool rr, ww, xx, d;
njn25e49d8e72002-09-23 09:36:25 +0000150
sewardj45f4e7c2005-09-27 19:20:21 +0000151 /* 'a' is the return value from a real kernel mmap, hence: */
152 vg_assert(VG_IS_PAGE_ALIGNED(a));
153 /* whereas len is whatever the syscall supplied. So: */
154 len = VG_PGROUNDUP(len);
fitzhardinge98abfc72003-12-16 02:05:15 +0000155
sewardj45f4e7c2005-09-27 19:20:21 +0000156 d = VG_(am_notify_client_mmap)( a, len, prot, flags, fd, offset );
fitzhardinge98abfc72003-12-16 02:05:15 +0000157
sewardj45f4e7c2005-09-27 19:20:21 +0000158 rr = toBool(prot & VKI_PROT_READ);
159 ww = toBool(prot & VKI_PROT_WRITE);
160 xx = toBool(prot & VKI_PROT_EXEC);
njn25e49d8e72002-09-23 09:36:25 +0000161
sewardj40f8ebe2002-10-23 21:46:13 +0000162 VG_TRACK( new_mem_mmap, a, len, rr, ww, xx );
sewardj45f4e7c2005-09-27 19:20:21 +0000163
164 if (d)
165 VG_(discard_translations)( (Addr64)a, (ULong)len,
166 "ML_(notify_aspacem_and_tool_of_mmap)" );
sewardjde4a1d02002-03-22 01:27:54 +0000167}
168
sewardj45f4e7c2005-09-27 19:20:21 +0000169/* Expand (or shrink) an existing mapping, potentially moving it at
170 the same time (controlled by the MREMAP_MAYMOVE flag). Nightmare.
171*/
172static
173SysRes do_mremap( Addr old_addr, SizeT old_len,
174 Addr new_addr, SizeT new_len,
175 UWord flags, ThreadId tid )
njn25e49d8e72002-09-23 09:36:25 +0000176{
sewardj45f4e7c2005-09-27 19:20:21 +0000177# define MIN_SIZET(_aa,_bb) (_aa) < (_bb) ? (_aa) : (_bb)
njn25e49d8e72002-09-23 09:36:25 +0000178
sewardj45f4e7c2005-09-27 19:20:21 +0000179 Bool ok, d;
180 NSegment* old_seg;
181 Addr advised;
182 Bool f_fixed = toBool(flags & VKI_MREMAP_FIXED);
183 Bool f_maymove = toBool(flags & VKI_MREMAP_MAYMOVE);
fitzhardinge1a303042003-12-22 08:48:50 +0000184
185 if (0)
sewardj45f4e7c2005-09-27 19:20:21 +0000186 VG_(printf)("do_remap (old %p %d) (new %p %d) %s %s\n",
187 old_addr,old_len,new_addr,new_len,
188 flags & VKI_MREMAP_MAYMOVE ? "MAYMOVE" : "",
189 flags & VKI_MREMAP_FIXED ? "FIXED" : "");
fitzhardinge1a303042003-12-22 08:48:50 +0000190
sewardj45f4e7c2005-09-27 19:20:21 +0000191 if (flags & ~(VKI_MREMAP_FIXED | VKI_MREMAP_MAYMOVE))
192 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000193
sewardj45f4e7c2005-09-27 19:20:21 +0000194 if (!VG_IS_PAGE_ALIGNED(old_addr))
195 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000196
sewardj45f4e7c2005-09-27 19:20:21 +0000197 old_len = VG_PGROUNDUP(old_len);
198 new_len = VG_PGROUNDUP(new_len);
fitzhardinge1a303042003-12-22 08:48:50 +0000199
sewardj45f4e7c2005-09-27 19:20:21 +0000200 if (new_len == 0)
201 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000202
sewardj45f4e7c2005-09-27 19:20:21 +0000203 /* kernel doesn't reject this, but we do. */
204 if (old_len == 0)
205 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000206
sewardj45f4e7c2005-09-27 19:20:21 +0000207 /* reject wraparounds */
208 if (old_addr + old_len < old_addr
209 || new_addr + new_len < new_len)
210 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000211
sewardj45f4e7c2005-09-27 19:20:21 +0000212 /* kernel rejects all fixed, no-move requests (which are
213 meaningless). */
214 if (f_fixed == True && f_maymove == False)
215 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000216
sewardj45f4e7c2005-09-27 19:20:21 +0000217 /* Stay away from non-client areas. */
218 if (!ML_(valid_client_addr)(old_addr, old_len, tid, "mremap(old_addr)"))
219 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000220
sewardj45f4e7c2005-09-27 19:20:21 +0000221 /* In all remaining cases, if the old range does not fall within a
222 single segment, fail. */
223 old_seg = VG_(am_find_nsegment)( old_addr );
224 if (old_addr < old_seg->start || old_addr+old_len-1 > old_seg->end)
225 goto eINVAL;
sewardjfdf619e2005-11-23 03:41:41 +0000226 if (old_seg->kind != SkAnonC && old_seg->kind != SkFileC)
sewardj45f4e7c2005-09-27 19:20:21 +0000227 goto eINVAL;
fitzhardinge1a303042003-12-22 08:48:50 +0000228
sewardj45f4e7c2005-09-27 19:20:21 +0000229 vg_assert(old_len > 0);
230 vg_assert(new_len > 0);
231 vg_assert(VG_IS_PAGE_ALIGNED(old_len));
232 vg_assert(VG_IS_PAGE_ALIGNED(new_len));
233 vg_assert(VG_IS_PAGE_ALIGNED(old_addr));
fitzhardinge1a303042003-12-22 08:48:50 +0000234
sewardj45f4e7c2005-09-27 19:20:21 +0000235 /* There are 3 remaining cases:
fitzhardinge1a303042003-12-22 08:48:50 +0000236
sewardj45f4e7c2005-09-27 19:20:21 +0000237 * maymove == False
238
239 new space has to be at old address, so:
240 - shrink -> unmap end
241 - same size -> do nothing
242 - grow -> if can grow in-place, do so, else fail
243
244 * maymove == True, fixed == False
245
246 new space can be anywhere, so:
247 - shrink -> unmap end
248 - same size -> do nothing
249 - grow -> if can grow in-place, do so, else
250 move to anywhere large enough, else fail
251
252 * maymove == True, fixed == True
253
254 new space must be at new address, so:
255
256 - if new address is not page aligned, fail
257 - if new address range overlaps old one, fail
258 - if new address range cannot be allocated, fail
259 - else move to new address range with new size
260 - else fail
261 */
262
263 if (f_maymove == False) {
264 /* new space has to be at old address */
265 if (new_len < old_len)
266 goto shrink_in_place;
267 if (new_len > old_len)
268 goto grow_in_place_or_fail;
269 goto same_in_place;
270 }
271
272 if (f_maymove == True && f_fixed == False) {
273 /* new space can be anywhere */
274 if (new_len < old_len)
275 goto shrink_in_place;
276 if (new_len > old_len)
277 goto grow_in_place_or_move_anywhere_or_fail;
278 goto same_in_place;
279 }
280
281 if (f_maymove == True && f_fixed == True) {
282 /* new space can only be at the new address */
283 if (!VG_IS_PAGE_ALIGNED(new_addr))
284 goto eINVAL;
285 if (new_addr+new_len-1 < old_addr || new_addr > old_addr+old_len-1) {
286 /* no overlap */
fitzhardinge1a303042003-12-22 08:48:50 +0000287 } else {
sewardj45f4e7c2005-09-27 19:20:21 +0000288 goto eINVAL;
289 }
290 if (new_addr == 0)
291 goto eINVAL;
292 /* VG_(am_get_advisory_client_simple) interprets zero to mean
293 non-fixed, which is not what we want */
294 advised = VG_(am_get_advisory_client_simple)(new_addr, new_len, &ok);
295 if (!ok || advised != new_addr)
296 goto eNOMEM;
297 ok = VG_(am_relocate_nooverlap_client)
298 ( &d, old_addr, old_len, new_addr, new_len );
299 if (ok) {
300 VG_TRACK( copy_mem_remap, old_addr, new_addr,
301 MIN_SIZET(old_len,new_len) );
302 if (new_len > old_len)
303 VG_TRACK( new_mem_mmap, new_addr+old_len, new_len-old_len,
304 old_seg->hasR, old_seg->hasW, old_seg->hasX );
305 VG_TRACK(die_mem_munmap, old_addr, old_len);
306 if (d) {
307 VG_(discard_translations)( old_addr, old_len, "do_remap(1)" );
308 VG_(discard_translations)( new_addr, new_len, "do_remap(2)" );
309 }
310 return VG_(mk_SysRes_Success)( new_addr );
311 }
312 goto eNOMEM;
313 }
fitzhardinge1a303042003-12-22 08:48:50 +0000314
sewardj45f4e7c2005-09-27 19:20:21 +0000315 /* end of the 3 cases */
316 /*NOTREACHED*/ vg_assert(0);
fitzhardinge1a303042003-12-22 08:48:50 +0000317
sewardj45f4e7c2005-09-27 19:20:21 +0000318 grow_in_place_or_move_anywhere_or_fail:
319 {
320 /* try growing it in-place */
321 Addr needA = old_addr + old_len;
322 SSizeT needL = new_len - old_len;
fitzhardinge1a303042003-12-22 08:48:50 +0000323
sewardj45f4e7c2005-09-27 19:20:21 +0000324 vg_assert(needL > 0);
325 if (needA == 0)
326 goto eINVAL;
327 /* VG_(am_get_advisory_client_simple) interprets zero to mean
328 non-fixed, which is not what we want */
329 advised = VG_(am_get_advisory_client_simple)( needA, needL, &ok );
330 if (ok && advised == needA) {
331 ok = VG_(am_extend_map_client)( &d, old_seg, needL );
332 if (ok) {
333 VG_TRACK( new_mem_mmap, needA, needL,
334 old_seg->hasR,
335 old_seg->hasW, old_seg->hasX );
336 if (d)
337 VG_(discard_translations)( needA, needL, "do_remap(3)" );
338 return VG_(mk_SysRes_Success)( old_addr );
fitzhardinge1a303042003-12-22 08:48:50 +0000339 }
340 }
341
sewardj45f4e7c2005-09-27 19:20:21 +0000342 /* that failed. Look elsewhere. */
343 advised = VG_(am_get_advisory_client_simple)( 0, new_len, &ok );
344 if (ok) {
345 /* assert new area does not overlap old */
346 vg_assert(advised+new_len-1 < old_addr
347 || advised > old_addr+old_len-1);
348 ok = VG_(am_relocate_nooverlap_client)
349 ( &d, old_addr, old_len, advised, new_len );
350 if (ok) {
351 VG_TRACK( copy_mem_remap, old_addr, advised,
352 MIN_SIZET(old_len,new_len) );
353 if (new_len > old_len)
354 VG_TRACK( new_mem_mmap, advised+old_len, new_len-old_len,
355 old_seg->hasR, old_seg->hasW, old_seg->hasX );
356 VG_TRACK(die_mem_munmap, old_addr, old_len);
357 if (d) {
358 VG_(discard_translations)( old_addr, old_len, "do_remap(4)" );
359 VG_(discard_translations)( advised, new_len, "do_remap(5)" );
360 }
361 return VG_(mk_SysRes_Success)( advised );
362 }
363 }
364 goto eNOMEM;
365 }
366 /*NOTREACHED*/ vg_assert(0);
367
368 grow_in_place_or_fail:
369 {
370 Addr needA = old_addr + old_len;
371 SizeT needL = new_len - old_len;
372 if (needA == 0)
373 goto eINVAL;
374 /* VG_(am_get_advisory_client_simple) interprets zero to mean
375 non-fixed, which is not what we want */
376 advised = VG_(am_get_advisory_client_simple)( needA, needL, &ok );
377 if (!ok || advised != needA)
378 goto eNOMEM;
379 ok = VG_(am_extend_map_client)( &d, old_seg, needL );
380 if (!ok)
381 goto eNOMEM;
382 VG_TRACK( new_mem_mmap, needA, needL,
383 old_seg->hasR, old_seg->hasW, old_seg->hasX );
384 if (d)
385 VG_(discard_translations)( needA, needL, "do_remap(6)" );
386 return VG_(mk_SysRes_Success)( old_addr );
387 }
388 /*NOTREACHED*/ vg_assert(0);
389
390 shrink_in_place:
391 {
392 SysRes sres = VG_(am_munmap_client)( &d, old_addr+new_len, old_len-new_len );
393 if (sres.isError)
394 return sres;
395 VG_TRACK( die_mem_munmap, old_addr+new_len, old_len-new_len );
396 if (d)
397 VG_(discard_translations)( old_addr+new_len, old_len-new_len,
398 "do_remap(7)" );
399 return VG_(mk_SysRes_Success)( old_addr );
400 }
401 /*NOTREACHED*/ vg_assert(0);
402
403 same_in_place:
404 return VG_(mk_SysRes_Success)( old_addr );
405 /*NOTREACHED*/ vg_assert(0);
406
407 eINVAL:
408 return VG_(mk_SysRes_Error)( VKI_EINVAL );
409 eNOMEM:
410 return VG_(mk_SysRes_Error)( VKI_ENOMEM );
411
412# undef MIN_SIZET
sewardjde4a1d02002-03-22 01:27:54 +0000413}
414
415
sewardja8d8e232005-06-07 20:04:56 +0000416/* ---------------------------------------------------------------------
417 File-descriptor tracking
418 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000419
rjwalshf5f536f2003-11-17 17:45:00 +0000420/* One of these is allocated for each open file descriptor. */
rjwalshf5f536f2003-11-17 17:45:00 +0000421typedef struct OpenFd
422{
423 Int fd; /* The file descriptor */
424 Char *pathname; /* NULL if not a regular file or unknown */
425 ExeContext *where; /* NULL if inherited from parent */
426 struct OpenFd *next, *prev;
427} OpenFd;
428
429/* List of allocated file descriptors. */
rjwalshf5f536f2003-11-17 17:45:00 +0000430static OpenFd *allocated_fds;
431
432/* Count of open file descriptors. */
sewardj0a400c72005-07-23 09:22:46 +0000433static Int fd_count = 0;
rjwalshf5f536f2003-11-17 17:45:00 +0000434
rjwalshf5f536f2003-11-17 17:45:00 +0000435
rjwalshf5f536f2003-11-17 17:45:00 +0000436/* Note the fact that a file descriptor was just closed. */
rjwalshf5f536f2003-11-17 17:45:00 +0000437static
njnc6168192004-11-29 13:54:10 +0000438void record_fd_close(ThreadId tid, Int fd)
rjwalshf5f536f2003-11-17 17:45:00 +0000439{
440 OpenFd *i = allocated_fds;
441
thughesad1c9562004-06-26 11:27:52 +0000442 if (fd >= VG_(fd_hard_limit))
rjwalsh02665ba2003-12-18 01:48:06 +0000443 return; /* Valgrind internal */
444
rjwalshf5f536f2003-11-17 17:45:00 +0000445 while(i) {
446 if(i->fd == fd) {
447 if(i->prev)
448 i->prev->next = i->next;
449 else
450 allocated_fds = i->next;
451 if(i->next)
452 i->next->prev = i->prev;
453 if(i->pathname)
fitzhardingea7728472003-12-16 01:48:38 +0000454 VG_(arena_free) (VG_AR_CORE, i->pathname);
455 VG_(arena_free) (VG_AR_CORE, i);
rjwalshf5f536f2003-11-17 17:45:00 +0000456 fd_count--;
457 break;
458 }
459 i = i->next;
460 }
461}
462
463/* Note the fact that a file descriptor was just opened. If the
464 tid is -1, this indicates an inherited fd. If the pathname is NULL,
465 this either indicates a non-standard file (i.e. a pipe or socket or
466 some such thing) or that we don't know the filename. If the fd is
467 already open, then we're probably doing a dup2() to an existing fd,
468 so just overwrite the existing one. */
njn4279a882005-08-26 03:43:28 +0000469void ML_(record_fd_open_with_given_name)(ThreadId tid, Int fd, char *pathname)
rjwalshf5f536f2003-11-17 17:45:00 +0000470{
471 OpenFd *i;
472
thughesad1c9562004-06-26 11:27:52 +0000473 if (fd >= VG_(fd_hard_limit))
fitzhardinge0e8bfcf2003-12-12 07:46:54 +0000474 return; /* Valgrind internal */
475
rjwalshf5f536f2003-11-17 17:45:00 +0000476 /* Check to see if this fd is already open. */
477 i = allocated_fds;
478 while (i) {
479 if (i->fd == fd) {
fitzhardingea7728472003-12-16 01:48:38 +0000480 if (i->pathname) VG_(arena_free)(VG_AR_CORE, i->pathname);
rjwalshf5f536f2003-11-17 17:45:00 +0000481 break;
482 }
483 i = i->next;
484 }
485
486 /* Not already one: allocate an OpenFd */
487 if (i == NULL) {
fitzhardingea7728472003-12-16 01:48:38 +0000488 i = VG_(arena_malloc)(VG_AR_CORE, sizeof(OpenFd));
rjwalshf5f536f2003-11-17 17:45:00 +0000489
490 i->prev = NULL;
491 i->next = allocated_fds;
492 if(allocated_fds) allocated_fds->prev = i;
493 allocated_fds = i;
494 fd_count++;
495 }
496
497 i->fd = fd;
njnf845f8f2005-06-23 02:26:47 +0000498 i->pathname = VG_(arena_strdup)(VG_AR_CORE, pathname);
njnd01fef72005-03-25 23:35:48 +0000499 i->where = (tid == -1) ? NULL : VG_(record_ExeContext)(tid);
rjwalshf5f536f2003-11-17 17:45:00 +0000500}
501
njnf845f8f2005-06-23 02:26:47 +0000502// Record opening of an fd, and find its name.
503static void record_fd_open_named(ThreadId tid, Int fd)
504{
505 static HChar buf[VKI_PATH_MAX];
506 Char* name;
507 if (VG_(resolve_filename)(fd, buf, VKI_PATH_MAX))
508 name = buf;
509 else
510 name = NULL;
511
njn4279a882005-08-26 03:43:28 +0000512 ML_(record_fd_open_with_given_name)(tid, fd, name);
njnf845f8f2005-06-23 02:26:47 +0000513}
514
515// Record opening of a nameless fd.
516void ML_(record_fd_open_nameless)(ThreadId tid, Int fd)
517{
njn4279a882005-08-26 03:43:28 +0000518 ML_(record_fd_open_with_given_name)(tid, fd, NULL);
njnf845f8f2005-06-23 02:26:47 +0000519}
520
rjwalshf5f536f2003-11-17 17:45:00 +0000521static
nethercote73b526f2004-10-31 18:48:21 +0000522Char *unix2name(struct vki_sockaddr_un *sa, UInt len, Char *name)
rjwalshf5f536f2003-11-17 17:45:00 +0000523{
nethercote73b526f2004-10-31 18:48:21 +0000524 if (sa == NULL || len == 0 || sa->sun_path[0] == '\0') {
rjwalshf5f536f2003-11-17 17:45:00 +0000525 VG_(sprintf)(name, "<unknown>");
526 } else {
527 VG_(sprintf)(name, "%s", sa->sun_path);
528 }
529
530 return name;
531}
532
533static
nethercote73b526f2004-10-31 18:48:21 +0000534Char *inet2name(struct vki_sockaddr_in *sa, UInt len, Char *name)
rjwalshf5f536f2003-11-17 17:45:00 +0000535{
nethercote73b526f2004-10-31 18:48:21 +0000536 if (sa == NULL || len == 0) {
rjwalshf5f536f2003-11-17 17:45:00 +0000537 VG_(sprintf)(name, "<unknown>");
538 } else {
tom329af4b2005-11-17 12:02:58 +0000539 UInt addr = VG_(ntohl)(sa->sin_addr.s_addr);
rjwalshf5f536f2003-11-17 17:45:00 +0000540 if (addr == 0) {
541 VG_(sprintf)(name, "<unbound>");
542 } else {
543 VG_(sprintf)(name, "%u.%u.%u.%u:%u",
tom329af4b2005-11-17 12:02:58 +0000544 (addr>>24) & 0xFF, (addr>>16) & 0xFF,
545 (addr>>8) & 0xFF, addr & 0xFF,
546 VG_(ntohs)(sa->sin_port));
rjwalshf5f536f2003-11-17 17:45:00 +0000547 }
548 }
549
550 return name;
551}
552
rjwalshf5f536f2003-11-17 17:45:00 +0000553/*
554 * Try get some details about a socket.
555 */
rjwalshf5f536f2003-11-17 17:45:00 +0000556static void
sewardj0a400c72005-07-23 09:22:46 +0000557getsockdetails(Int fd)
rjwalshf5f536f2003-11-17 17:45:00 +0000558{
559 union u {
nethercote73b526f2004-10-31 18:48:21 +0000560 struct vki_sockaddr a;
561 struct vki_sockaddr_in in;
562 struct vki_sockaddr_un un;
rjwalshf5f536f2003-11-17 17:45:00 +0000563 } laddr;
nethercote73b526f2004-10-31 18:48:21 +0000564 UInt llen;
rjwalshf5f536f2003-11-17 17:45:00 +0000565
566 llen = sizeof(laddr);
567 VG_(memset)(&laddr, 0, llen);
568
569 if(VG_(getsockname)(fd, (struct vki_sockaddr *)&(laddr.a), &llen) != -1) {
570 switch(laddr.a.sa_family) {
nethercote73b526f2004-10-31 18:48:21 +0000571 case VKI_AF_INET: {
rjwalshf5f536f2003-11-17 17:45:00 +0000572 static char lname[32];
573 static char pname[32];
nethercote73b526f2004-10-31 18:48:21 +0000574 struct vki_sockaddr_in paddr;
575 UInt plen = sizeof(struct vki_sockaddr_in);
rjwalshf5f536f2003-11-17 17:45:00 +0000576
577 if(VG_(getpeername)(fd, (struct vki_sockaddr *)&paddr, &plen) != -1) {
578 VG_(message)(Vg_UserMsg, "Open AF_INET socket %d: %s <-> %s", fd,
579 inet2name(&(laddr.in), llen, lname),
580 inet2name(&paddr, plen, pname));
581 } else {
582 VG_(message)(Vg_UserMsg, "Open AF_INET socket %d: %s <-> unbound",
583 fd, inet2name(&(laddr.in), llen, lname));
584 }
585 return;
586 }
nethercote73b526f2004-10-31 18:48:21 +0000587 case VKI_AF_UNIX: {
rjwalshf5f536f2003-11-17 17:45:00 +0000588 static char lname[256];
589 VG_(message)(Vg_UserMsg, "Open AF_UNIX socket %d: %s", fd,
590 unix2name(&(laddr.un), llen, lname));
591 return;
592 }
593 default:
594 VG_(message)(Vg_UserMsg, "Open pf-%d socket %d:",
595 laddr.a.sa_family, fd);
596 return;
597 }
598 }
599
600 VG_(message)(Vg_UserMsg, "Open socket %d:", fd);
601}
602
603
nethercote3a42fb82004-08-03 18:08:50 +0000604/* Dump out a summary, and a more detailed list, of open file descriptors. */
605void VG_(show_open_fds) ()
rjwalshf5f536f2003-11-17 17:45:00 +0000606{
607 OpenFd *i = allocated_fds;
608
nethercote3a42fb82004-08-03 18:08:50 +0000609 VG_(message)(Vg_UserMsg, "FILE DESCRIPTORS: %d open at exit.", fd_count);
rjwalshf5f536f2003-11-17 17:45:00 +0000610
611 while(i) {
612 if(i->pathname) {
613 VG_(message)(Vg_UserMsg, "Open file descriptor %d: %s", i->fd,
614 i->pathname);
615 } else {
sewardj0a400c72005-07-23 09:22:46 +0000616 Int val;
nethercote73b526f2004-10-31 18:48:21 +0000617 UInt len = sizeof(val);
rjwalshf5f536f2003-11-17 17:45:00 +0000618
nethercote73b526f2004-10-31 18:48:21 +0000619 if (VG_(getsockopt)(i->fd, VKI_SOL_SOCKET, VKI_SO_TYPE, &val, &len) == -1) {
rjwalshf5f536f2003-11-17 17:45:00 +0000620 VG_(message)(Vg_UserMsg, "Open file descriptor %d:", i->fd);
621 } else {
622 getsockdetails(i->fd);
623 }
624 }
625
626 if(i->where) {
627 VG_(pp_ExeContext)(i->where);
628 VG_(message)(Vg_UserMsg, "");
629 } else {
630 VG_(message)(Vg_UserMsg, " <inherited from parent>");
631 VG_(message)(Vg_UserMsg, "");
632 }
633
634 i = i->next;
635 }
636
637 VG_(message)(Vg_UserMsg, "");
638}
639
640/* If /proc/self/fd doesn't exist for some weird reason (like you've
641 got a kernel that doesn't have /proc support compiled in), then we
642 need to find out what file descriptors we inherited from our parent
643 process the hard way - by checking each fd in turn. */
644
645static
tom7c787822005-11-11 12:32:10 +0000646void do_hacky_preopened(void)
rjwalshf5f536f2003-11-17 17:45:00 +0000647{
648 struct vki_rlimit lim;
sewardj0a400c72005-07-23 09:22:46 +0000649 UInt count;
650 Int i;
rjwalshf5f536f2003-11-17 17:45:00 +0000651
nethercote620154f2004-11-12 21:21:07 +0000652 if (VG_(getrlimit) (VKI_RLIMIT_NOFILE, &lim) == -1) {
rjwalshf5f536f2003-11-17 17:45:00 +0000653 /* Hmm. getrlimit() failed. Now we're screwed, so just choose
654 an arbitrarily high number. 1024 happens to be the limit in
655 the 2.4 kernels. */
656 count = 1024;
657 } else {
658 count = lim.rlim_cur;
659 }
660
661 for (i = 0; i < count; i++)
662 if(VG_(fcntl)(i, VKI_F_GETFL, 0) != -1)
njnf845f8f2005-06-23 02:26:47 +0000663 ML_(record_fd_open_nameless)(-1, i);
rjwalshf5f536f2003-11-17 17:45:00 +0000664}
665
666/* Initialize the list of open file descriptors with the file descriptors
667 we inherited from out parent process. */
668
669void VG_(init_preopened_fds)()
670{
sewardj0a400c72005-07-23 09:22:46 +0000671 Int ret;
rjwalshf5f536f2003-11-17 17:45:00 +0000672 struct vki_dirent d;
sewardj92645592005-07-23 09:18:34 +0000673 SysRes f;
rjwalshf5f536f2003-11-17 17:45:00 +0000674
675 f = VG_(open)("/proc/self/fd", VKI_O_RDONLY, 0);
sewardj92645592005-07-23 09:18:34 +0000676 if (f.isError) {
rjwalshf5f536f2003-11-17 17:45:00 +0000677 do_hacky_preopened();
678 return;
679 }
680
sewardj92645592005-07-23 09:18:34 +0000681 while ((ret = VG_(getdents)(f.val, &d, sizeof(d))) != 0) {
njnf845f8f2005-06-23 02:26:47 +0000682 if (ret == -1)
rjwalshf5f536f2003-11-17 17:45:00 +0000683 goto out;
684
njnf845f8f2005-06-23 02:26:47 +0000685 if (VG_(strcmp)(d.d_name, ".") && VG_(strcmp)(d.d_name, "..")) {
sewardj0a400c72005-07-23 09:22:46 +0000686 Int fno = VG_(atoll)(d.d_name);
rjwalshf5f536f2003-11-17 17:45:00 +0000687
sewardj92645592005-07-23 09:18:34 +0000688 if (fno != f.val)
njnf845f8f2005-06-23 02:26:47 +0000689 if (VG_(clo_track_fds))
690 record_fd_open_named(-1, fno);
rjwalshf5f536f2003-11-17 17:45:00 +0000691 }
692
sewardj92645592005-07-23 09:18:34 +0000693 VG_(lseek)(f.val, d.d_off, VKI_SEEK_SET);
rjwalshf5f536f2003-11-17 17:45:00 +0000694 }
695
sewardj92645592005-07-23 09:18:34 +0000696 out:
697 VG_(close)(f.val);
rjwalshf5f536f2003-11-17 17:45:00 +0000698}
699
sewardjde4a1d02002-03-22 01:27:54 +0000700static
sewardj8c824512002-04-14 04:16:48 +0000701Char *strdupcat ( const Char *s1, const Char *s2, ArenaId aid )
sewardjde4a1d02002-03-22 01:27:54 +0000702{
703 UInt len = VG_(strlen) ( s1 ) + VG_(strlen) ( s2 ) + 1;
njn25e49d8e72002-09-23 09:36:25 +0000704 Char *result = VG_(arena_malloc) ( aid, len );
sewardjde4a1d02002-03-22 01:27:54 +0000705 VG_(strcpy) ( result, s1 );
706 VG_(strcat) ( result, s2 );
707 return result;
708}
709
710static
tom56e1c842005-07-18 22:41:33 +0000711void pre_mem_read_sendmsg ( ThreadId tid, Bool read,
nethercote928a5f72004-11-03 18:10:37 +0000712 Char *msg, Addr base, SizeT size )
sewardjde4a1d02002-03-22 01:27:54 +0000713{
njn9f46df62005-03-13 18:11:44 +0000714 Char *outmsg = strdupcat ( "socketcall.sendmsg", msg, VG_AR_CORE );
nethercoteef0c7662004-11-06 15:38:43 +0000715 PRE_MEM_READ( outmsg, base, size );
njn9f46df62005-03-13 18:11:44 +0000716 VG_(arena_free) ( VG_AR_CORE, outmsg );
sewardjde4a1d02002-03-22 01:27:54 +0000717}
718
719static
tom56e1c842005-07-18 22:41:33 +0000720void pre_mem_write_recvmsg ( ThreadId tid, Bool read,
nethercote928a5f72004-11-03 18:10:37 +0000721 Char *msg, Addr base, SizeT size )
sewardjde4a1d02002-03-22 01:27:54 +0000722{
njn9f46df62005-03-13 18:11:44 +0000723 Char *outmsg = strdupcat ( "socketcall.recvmsg", msg, VG_AR_CORE );
tom56e1c842005-07-18 22:41:33 +0000724 if ( read )
725 PRE_MEM_READ( outmsg, base, size );
726 else
727 PRE_MEM_WRITE( outmsg, base, size );
njn9f46df62005-03-13 18:11:44 +0000728 VG_(arena_free) ( VG_AR_CORE, outmsg );
sewardjde4a1d02002-03-22 01:27:54 +0000729}
730
731static
tom56e1c842005-07-18 22:41:33 +0000732void post_mem_write_recvmsg ( ThreadId tid, Bool read,
nethercote928a5f72004-11-03 18:10:37 +0000733 Char *fieldName, Addr base, SizeT size )
sewardjde4a1d02002-03-22 01:27:54 +0000734{
tom56e1c842005-07-18 22:41:33 +0000735 if ( !read )
736 POST_MEM_WRITE( base, size );
sewardjde4a1d02002-03-22 01:27:54 +0000737}
738
739static
sewardj8c824512002-04-14 04:16:48 +0000740void msghdr_foreachfield (
njn72718642003-07-24 08:45:32 +0000741 ThreadId tid,
nethercote73b526f2004-10-31 18:48:21 +0000742 struct vki_msghdr *msg,
tom56e1c842005-07-18 22:41:33 +0000743 void (*foreach_func)( ThreadId, Bool, Char *, Addr, SizeT )
sewardj8c824512002-04-14 04:16:48 +0000744 )
sewardjde4a1d02002-03-22 01:27:54 +0000745{
746 if ( !msg )
747 return;
748
tom56e1c842005-07-18 22:41:33 +0000749 foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_name, sizeof( msg->msg_name ) );
750 foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_namelen, sizeof( msg->msg_namelen ) );
751 foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_iov, sizeof( msg->msg_iov ) );
752 foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_iovlen, sizeof( msg->msg_iovlen ) );
753 foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_control, sizeof( msg->msg_control ) );
754 foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_controllen, sizeof( msg->msg_controllen ) );
755 foreach_func ( tid, True, "(msg)", (Addr)&msg->msg_flags, sizeof( msg->msg_flags ) );
sewardjde4a1d02002-03-22 01:27:54 +0000756
757 if ( msg->msg_name )
tom56e1c842005-07-18 22:41:33 +0000758 foreach_func ( tid, False,
sewardj8c824512002-04-14 04:16:48 +0000759 "(msg.msg_name)",
sewardjde4a1d02002-03-22 01:27:54 +0000760 (Addr)msg->msg_name, msg->msg_namelen );
761
762 if ( msg->msg_iov ) {
nethercote73b526f2004-10-31 18:48:21 +0000763 struct vki_iovec *iov = msg->msg_iov;
sewardjde4a1d02002-03-22 01:27:54 +0000764 UInt i;
765
tom56e1c842005-07-18 22:41:33 +0000766 foreach_func ( tid, True,
sewardj8c824512002-04-14 04:16:48 +0000767 "(msg.msg_iov)",
nethercote73b526f2004-10-31 18:48:21 +0000768 (Addr)iov, msg->msg_iovlen * sizeof( struct vki_iovec ) );
sewardjde4a1d02002-03-22 01:27:54 +0000769
770 for ( i = 0; i < msg->msg_iovlen; ++i, ++iov )
tom56e1c842005-07-18 22:41:33 +0000771 foreach_func ( tid, False,
sewardj8c824512002-04-14 04:16:48 +0000772 "(msg.msg_iov[i]",
sewardjde4a1d02002-03-22 01:27:54 +0000773 (Addr)iov->iov_base, iov->iov_len );
774 }
775
776 if ( msg->msg_control )
tom56e1c842005-07-18 22:41:33 +0000777 foreach_func ( tid, False,
sewardj8c824512002-04-14 04:16:48 +0000778 "(msg.msg_control)",
sewardjde4a1d02002-03-22 01:27:54 +0000779 (Addr)msg->msg_control, msg->msg_controllen );
780}
781
sewardjb5f6f512005-03-10 23:59:00 +0000782static void check_cmsg_for_fds(ThreadId tid, struct vki_msghdr *msg)
rjwalshf5f536f2003-11-17 17:45:00 +0000783{
nethercote73b526f2004-10-31 18:48:21 +0000784 struct vki_cmsghdr *cm = VKI_CMSG_FIRSTHDR(msg);
rjwalshf5f536f2003-11-17 17:45:00 +0000785
786 while (cm) {
nethercote73b526f2004-10-31 18:48:21 +0000787 if (cm->cmsg_level == VKI_SOL_SOCKET &&
788 cm->cmsg_type == VKI_SCM_RIGHTS ) {
sewardj0a400c72005-07-23 09:22:46 +0000789 Int *fds = (Int *) VKI_CMSG_DATA(cm);
790 Int fdc = (cm->cmsg_len - VKI_CMSG_ALIGN(sizeof(struct vki_cmsghdr)))
rjwalshf5f536f2003-11-17 17:45:00 +0000791 / sizeof(int);
sewardj0a400c72005-07-23 09:22:46 +0000792 Int i;
rjwalshf5f536f2003-11-17 17:45:00 +0000793
794 for (i = 0; i < fdc; i++)
795 if(VG_(clo_track_fds))
nethercote493dd182004-02-24 23:57:47 +0000796 // XXX: must we check the range on these fds with
cerion7b2c38c2005-06-23 07:52:54 +0000797 // ML_(fd_allowed)()?
njnf845f8f2005-06-23 02:26:47 +0000798 record_fd_open_named(tid, fds[i]);
rjwalshf5f536f2003-11-17 17:45:00 +0000799 }
800
nethercote73b526f2004-10-31 18:48:21 +0000801 cm = VKI_CMSG_NXTHDR(msg, cm);
rjwalshf5f536f2003-11-17 17:45:00 +0000802 }
803}
804
sewardjc483e8f2002-05-03 21:01:35 +0000805static
jsgf855d93d2003-10-13 22:26:55 +0000806void pre_mem_read_sockaddr ( ThreadId tid,
sewardja8d8e232005-06-07 20:04:56 +0000807 Char *description,
808 struct vki_sockaddr *sa, UInt salen )
sewardjc483e8f2002-05-03 21:01:35 +0000809{
sewardjff7c1ab2003-02-24 21:55:34 +0000810 Char *outmsg;
811
812 /* NULL/zero-length sockaddrs are legal */
813 if ( sa == NULL || salen == 0 ) return;
814
njn9f46df62005-03-13 18:11:44 +0000815 outmsg = VG_(arena_malloc) ( VG_AR_CORE,
nethercote73b526f2004-10-31 18:48:21 +0000816 VG_(strlen)( description ) + 30 );
sewardjc483e8f2002-05-03 21:01:35 +0000817
818 VG_(sprintf) ( outmsg, description, ".sa_family" );
nethercoteef0c7662004-11-06 15:38:43 +0000819 PRE_MEM_READ( outmsg, (Addr) &sa->sa_family, sizeof(vki_sa_family_t));
jsgf855d93d2003-10-13 22:26:55 +0000820
sewardjc483e8f2002-05-03 21:01:35 +0000821 switch (sa->sa_family) {
822
nethercote73b526f2004-10-31 18:48:21 +0000823 case VKI_AF_UNIX:
sewardjc483e8f2002-05-03 21:01:35 +0000824 VG_(sprintf) ( outmsg, description, ".sun_path" );
nethercoteef0c7662004-11-06 15:38:43 +0000825 PRE_MEM_RASCIIZ( outmsg,
nethercote73b526f2004-10-31 18:48:21 +0000826 (Addr) ((struct vki_sockaddr_un *) sa)->sun_path);
sewardjc483e8f2002-05-03 21:01:35 +0000827 break;
828
nethercote73b526f2004-10-31 18:48:21 +0000829 case VKI_AF_INET:
sewardjc483e8f2002-05-03 21:01:35 +0000830 VG_(sprintf) ( outmsg, description, ".sin_port" );
nethercoteef0c7662004-11-06 15:38:43 +0000831 PRE_MEM_READ( outmsg,
nethercote73b526f2004-10-31 18:48:21 +0000832 (Addr) &((struct vki_sockaddr_in *) sa)->sin_port,
833 sizeof (((struct vki_sockaddr_in *) sa)->sin_port));
sewardjc483e8f2002-05-03 21:01:35 +0000834 VG_(sprintf) ( outmsg, description, ".sin_addr" );
nethercoteef0c7662004-11-06 15:38:43 +0000835 PRE_MEM_READ( outmsg,
nethercote73b526f2004-10-31 18:48:21 +0000836 (Addr) &((struct vki_sockaddr_in *) sa)->sin_addr,
837 sizeof (struct vki_in_addr));
sewardjc483e8f2002-05-03 21:01:35 +0000838 break;
839
nethercote73b526f2004-10-31 18:48:21 +0000840 case VKI_AF_INET6:
sewardjc483e8f2002-05-03 21:01:35 +0000841 VG_(sprintf) ( outmsg, description, ".sin6_port" );
nethercoteef0c7662004-11-06 15:38:43 +0000842 PRE_MEM_READ( outmsg,
nethercote73b526f2004-10-31 18:48:21 +0000843 (Addr) &((struct vki_sockaddr_in6 *) sa)->sin6_port,
844 sizeof (((struct vki_sockaddr_in6 *) sa)->sin6_port));
sewardjc483e8f2002-05-03 21:01:35 +0000845 VG_(sprintf) ( outmsg, description, ".sin6_flowinfo" );
nethercoteef0c7662004-11-06 15:38:43 +0000846 PRE_MEM_READ( outmsg,
nethercote73b526f2004-10-31 18:48:21 +0000847 (Addr) &((struct vki_sockaddr_in6 *) sa)->sin6_flowinfo,
848 sizeof (__vki_u32));
sewardjc483e8f2002-05-03 21:01:35 +0000849 VG_(sprintf) ( outmsg, description, ".sin6_addr" );
nethercoteef0c7662004-11-06 15:38:43 +0000850 PRE_MEM_READ( outmsg,
nethercote73b526f2004-10-31 18:48:21 +0000851 (Addr) &((struct vki_sockaddr_in6 *) sa)->sin6_addr,
852 sizeof (struct vki_in6_addr));
sewardjc483e8f2002-05-03 21:01:35 +0000853 VG_(sprintf) ( outmsg, description, ".sin6_scope_id" );
nethercoteef0c7662004-11-06 15:38:43 +0000854 PRE_MEM_READ( outmsg,
nethercote73b526f2004-10-31 18:48:21 +0000855 (Addr) &((struct vki_sockaddr_in6 *) sa)->sin6_scope_id,
856 sizeof (__vki_u32));
sewardjc483e8f2002-05-03 21:01:35 +0000857 break;
858
859 default:
860 VG_(sprintf) ( outmsg, description, "" );
nethercoteef0c7662004-11-06 15:38:43 +0000861 PRE_MEM_READ( outmsg, (Addr) sa, salen );
sewardjc483e8f2002-05-03 21:01:35 +0000862 break;
863 }
864
njn9f46df62005-03-13 18:11:44 +0000865 VG_(arena_free) ( VG_AR_CORE, outmsg );
sewardjc483e8f2002-05-03 21:01:35 +0000866}
867
njn25e49d8e72002-09-23 09:36:25 +0000868/* Dereference a pointer to a UInt. */
njn72718642003-07-24 08:45:32 +0000869static UInt deref_UInt ( ThreadId tid, Addr a, Char* s )
njn25e49d8e72002-09-23 09:36:25 +0000870{
871 UInt* a_p = (UInt*)a;
nethercoteef0c7662004-11-06 15:38:43 +0000872 PRE_MEM_READ( s, (Addr)a_p, sizeof(UInt) );
njn25e49d8e72002-09-23 09:36:25 +0000873 if (a_p == NULL)
874 return 0;
875 else
876 return *a_p;
877}
878
njn25e49d8e72002-09-23 09:36:25 +0000879static
njn72718642003-07-24 08:45:32 +0000880void buf_and_len_pre_check( ThreadId tid, Addr buf_p, Addr buflen_p,
njn25e49d8e72002-09-23 09:36:25 +0000881 Char* buf_s, Char* buflen_s )
882{
njn51d827b2005-05-09 01:02:08 +0000883 if (VG_(tdict).track_pre_mem_write) {
njn72718642003-07-24 08:45:32 +0000884 UInt buflen_in = deref_UInt( tid, buflen_p, buflen_s);
njn25e49d8e72002-09-23 09:36:25 +0000885 if (buflen_in > 0) {
njn51d827b2005-05-09 01:02:08 +0000886 VG_(tdict).track_pre_mem_write( Vg_CoreSysCall, tid, buf_s, buf_p, buflen_in );
njn25e49d8e72002-09-23 09:36:25 +0000887 }
888 }
889}
890
891static
sewardja8d8e232005-06-07 20:04:56 +0000892void buf_and_len_post_check( ThreadId tid, SysRes res,
njn25e49d8e72002-09-23 09:36:25 +0000893 Addr buf_p, Addr buflen_p, Char* s )
894{
sewardja8d8e232005-06-07 20:04:56 +0000895 if (!res.isError && VG_(tdict).track_post_mem_write) {
njn72718642003-07-24 08:45:32 +0000896 UInt buflen_out = deref_UInt( tid, buflen_p, s);
njn25e49d8e72002-09-23 09:36:25 +0000897 if (buflen_out > 0 && buf_p != (Addr)NULL) {
njn51d827b2005-05-09 01:02:08 +0000898 VG_(tdict).track_post_mem_write( Vg_CoreSysCall, tid, buf_p, buflen_out );
njn25e49d8e72002-09-23 09:36:25 +0000899 }
900 }
901}
902
903/* ---------------------------------------------------------------------
904 Data seg end, for brk()
905 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +0000906
sewardj45f4e7c2005-09-27 19:20:21 +0000907/* +--------+------------+
908 | anon | resvn |
909 +--------+------------+
nethercotece471262004-08-25 13:43:44 +0000910
sewardj45f4e7c2005-09-27 19:20:21 +0000911 ^ ^ ^
912 | | boundary is page aligned
913 | VG_(brk_limit) -- no alignment constraint
914 VG_(brk_base) -- page aligned -- does not move
915
916 Both the anon part and the reservation part are always at least
917 one page.
918*/
919
920/* Set the new data segment end to NEWBRK. If this succeeds, return
921 NEWBRK, else return the current data segment end. */
922
923static Addr do_brk ( Addr newbrk )
924{
925 NSegment *aseg, *rseg;
926 Addr newbrkP;
927 SizeT delta;
928 Bool ok;
929 Bool debug = False;
fitzhardinge98abfc72003-12-16 02:05:15 +0000930
931 if (debug)
sewardj548be6d2005-02-16 01:31:37 +0000932 VG_(printf)("\ndo_brk: brk_base=%p brk_limit=%p newbrk=%p\n",
fitzhardinge98abfc72003-12-16 02:05:15 +0000933 VG_(brk_base), VG_(brk_limit), newbrk);
934
sewardj79048ce2005-02-18 08:28:32 +0000935# if 0
sewardje517b802005-02-16 01:58:51 +0000936 if (0) show_segments("in_brk");
sewardj79048ce2005-02-18 08:28:32 +0000937# endif
sewardj548be6d2005-02-16 01:31:37 +0000938
sewardj45f4e7c2005-09-27 19:20:21 +0000939 if (newbrk < VG_(brk_base))
940 /* Clearly impossible. */
941 goto bad;
fitzhardinge98abfc72003-12-16 02:05:15 +0000942
sewardj45f4e7c2005-09-27 19:20:21 +0000943 if (newbrk >= VG_(brk_base) && newbrk < VG_(brk_limit)) {
944 /* shrinking the data segment. Be lazy and don't munmap the
945 excess area. */
946 NSegment* seg = VG_(am_find_nsegment)(newbrk);
947 if (seg && seg->hasT)
948 VG_(discard_translations)( newbrk, VG_(brk_limit) - newbrk,
949 "do_brk(shrink)" );
950 VG_(brk_limit) = newbrk;
951 return newbrk;
952 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000953
sewardj45f4e7c2005-09-27 19:20:21 +0000954 /* otherwise we're expanding the brk segment. */
tom8e5963d2005-10-06 14:49:21 +0000955 if (VG_(brk_limit) > VG_(brk_base))
956 aseg = VG_(am_find_nsegment)( VG_(brk_limit)-1 );
957 else
958 aseg = VG_(am_find_nsegment)( VG_(brk_limit) );
sewardj45f4e7c2005-09-27 19:20:21 +0000959 rseg = VG_(am_next_nsegment)( aseg, True/*forwards*/ );
fitzhardinge98abfc72003-12-16 02:05:15 +0000960
sewardj45f4e7c2005-09-27 19:20:21 +0000961 /* These should be assured by setup_client_dataseg in m_main. */
962 vg_assert(aseg);
963 vg_assert(rseg);
964 vg_assert(aseg->kind == SkAnonC);
965 vg_assert(rseg->kind == SkResvn);
966 vg_assert(aseg->end+1 == rseg->start);
fitzhardinge98abfc72003-12-16 02:05:15 +0000967
sewardj45f4e7c2005-09-27 19:20:21 +0000968 vg_assert(newbrk >= VG_(brk_base));
969 if (newbrk <= rseg->start) {
970 /* still fits within the anon segment. */
971 VG_(brk_limit) = newbrk;
972 return newbrk;
973 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000974
sewardj45f4e7c2005-09-27 19:20:21 +0000975 if (newbrk >= rseg->end+1 - VKI_PAGE_SIZE) {
976 /* request is too large -- the resvn would fall below 1 page,
977 which isn't allowed. */
978 goto bad;
979 }
fitzhardinge98abfc72003-12-16 02:05:15 +0000980
sewardj45f4e7c2005-09-27 19:20:21 +0000981 newbrkP = VG_PGROUNDUP(newbrk);
982 vg_assert(newbrkP > rseg->start && newbrkP < rseg->end+1 - VKI_PAGE_SIZE);
983 delta = newbrkP - rseg->start;
984 vg_assert(delta > 0);
985 vg_assert(VG_IS_PAGE_ALIGNED(delta));
986
987 ok = VG_(am_extend_into_adjacent_reservation_client)( aseg, delta );
988 if (!ok) goto bad;
fitzhardinge98abfc72003-12-16 02:05:15 +0000989
sewardj45f4e7c2005-09-27 19:20:21 +0000990 VG_(brk_limit) = newbrk;
991 return newbrk;
fitzhardinge98abfc72003-12-16 02:05:15 +0000992
sewardj45f4e7c2005-09-27 19:20:21 +0000993 bad:
994 return VG_(brk_limit);
fitzhardinge98abfc72003-12-16 02:05:15 +0000995}
996
997
njn25e49d8e72002-09-23 09:36:25 +0000998/* ---------------------------------------------------------------------
jsgf855d93d2003-10-13 22:26:55 +0000999 Vet file descriptors for sanity
1000 ------------------------------------------------------------------ */
sewardj04236902005-10-04 22:27:22 +00001001/*
1002> - what does the "Bool soft" parameter mean?
1003
1004(Tom Hughes, 3 Oct 05):
1005
1006Whether or not to consider a file descriptor invalid if it is above
1007the current soft limit.
1008
1009Basically if we are testing whether a newly created file descriptor is
1010valid (in a post handler) then we set soft to true, and if we are
1011testing whether a file descriptor that is about to be used (in a pre
1012handler) is valid [viz, an already-existing fd] then we set it to false.
1013
1014The point is that if the (virtual) soft limit is lowered then any
1015existing descriptors can still be read/written/closed etc (so long as
1016they are below the valgrind reserved descriptors) but no new
1017descriptors can be created above the new soft limit.
1018
1019(jrs 4 Oct 05: in which case, I've renamed it "isNewFd")
1020*/
jsgf855d93d2003-10-13 22:26:55 +00001021
1022/* Return true if we're allowed to use or create this fd */
sewardj04236902005-10-04 22:27:22 +00001023Bool ML_(fd_allowed)(Int fd, const Char *syscallname, ThreadId tid, Bool isNewFd)
jsgf855d93d2003-10-13 22:26:55 +00001024{
sewardj04236902005-10-04 22:27:22 +00001025 Bool allowed = True;
1026
1027 /* hard limits always apply */
1028 if (fd < 0 || fd >= VG_(fd_hard_limit))
1029 allowed = False;
1030
1031 /* hijacking the logging fd is never allowed */
1032 if (fd == VG_(clo_log_fd))
1033 allowed = False;
1034
1035 /* if creating a new fd (rather than using an existing one), the
1036 soft limit must also be observed */
1037 if (isNewFd && fd >= VG_(fd_soft_limit))
1038 allowed = False;
1039
1040 /* this looks like it ought to be included, but causes problems: */
1041 /*
1042 if (fd == 2 && VG_(debugLog_getLevel)() > 0)
1043 allowed = False;
1044 */
1045 /* The difficulty is as follows: consider a program P which expects
1046 to be able to mess with (redirect) its own stderr (fd 2).
1047 Usually to deal with P we would issue command line flags to send
1048 logging somewhere other than stderr, so as not to disrupt P.
1049 The problem is that -d unilaterally hijacks stderr with no
1050 consultation with P. And so, if this check is enabled, P will
1051 work OK normally but fail if -d is issued.
1052
1053 Basically -d is a hack and you take your chances when using it.
1054 It's very useful for low level debugging -- particularly at
1055 startup -- and having its presence change the behaviour of the
1056 client is exactly what we don't want. */
1057
1058 /* croak? */
1059 if ((!allowed) && VG_(showing_core_errors)() ) {
jsewardd9320a42003-12-12 06:40:05 +00001060 VG_(message)(Vg_UserMsg,
1061 "Warning: invalid file descriptor %d in syscall %s()",
nethercote1543adf2004-10-25 15:43:21 +00001062 fd, syscallname);
nethercotef8548672004-06-21 12:42:35 +00001063 if (fd == VG_(clo_log_fd))
jsewardd9320a42003-12-12 06:40:05 +00001064 VG_(message)(Vg_UserMsg,
nethercotef8548672004-06-21 12:42:35 +00001065 " Use --log-fd=<number> to select an alternative log fd.");
jsgf855d93d2003-10-13 22:26:55 +00001066 if (VG_(clo_verbosity) > 1) {
njnd01fef72005-03-25 23:35:48 +00001067 VG_(get_and_pp_StackTrace)(tid, VG_(clo_backtrace_size));
jsgf855d93d2003-10-13 22:26:55 +00001068 }
jsgf855d93d2003-10-13 22:26:55 +00001069 }
sewardj04236902005-10-04 22:27:22 +00001070
1071 return allowed;
jsgf855d93d2003-10-13 22:26:55 +00001072}
1073
1074
1075/* ---------------------------------------------------------------------
sewardj9efbbef2005-03-01 16:45:23 +00001076 Deal with a bunch of socket-related syscalls
1077 ------------------------------------------------------------------ */
1078
1079/* ------ */
1080
sewardj987a8eb2005-03-01 19:00:30 +00001081void
sewardj7eb7c582005-06-23 01:02:53 +00001082ML_(generic_PRE_sys_socketpair) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001083 UWord arg0, UWord arg1,
1084 UWord arg2, UWord arg3 )
1085{
1086 /* int socketpair(int d, int type, int protocol, int sv[2]); */
1087 PRE_MEM_WRITE( "socketcall.socketpair(sv)",
1088 arg3, 2*sizeof(int) );
1089}
1090
sewardja8d8e232005-06-07 20:04:56 +00001091SysRes
sewardj7eb7c582005-06-23 01:02:53 +00001092ML_(generic_POST_sys_socketpair) ( ThreadId tid,
sewardja8d8e232005-06-07 20:04:56 +00001093 SysRes res,
sewardj987a8eb2005-03-01 19:00:30 +00001094 UWord arg0, UWord arg1,
1095 UWord arg2, UWord arg3 )
sewardj9efbbef2005-03-01 16:45:23 +00001096{
sewardja8d8e232005-06-07 20:04:56 +00001097 SysRes r = res;
sewardj9efbbef2005-03-01 16:45:23 +00001098 Int fd1 = ((Int*)arg3)[0];
1099 Int fd2 = ((Int*)arg3)[1];
tom60a4b0b2005-10-12 10:45:27 +00001100 vg_assert(!res.isError); /* guaranteed by caller */
sewardj9efbbef2005-03-01 16:45:23 +00001101 POST_MEM_WRITE( arg3, 2*sizeof(int) );
sewardj7eb7c582005-06-23 01:02:53 +00001102 if (!ML_(fd_allowed)(fd1, "socketcall.socketpair", tid, True) ||
1103 !ML_(fd_allowed)(fd2, "socketcall.socketpair", tid, True)) {
sewardj9efbbef2005-03-01 16:45:23 +00001104 VG_(close)(fd1);
1105 VG_(close)(fd2);
sewardja8d8e232005-06-07 20:04:56 +00001106 r = VG_(mk_SysRes_Error)( VKI_EMFILE );
sewardj9efbbef2005-03-01 16:45:23 +00001107 } else {
1108 POST_MEM_WRITE( arg3, 2*sizeof(int) );
1109 if (VG_(clo_track_fds)) {
njnf845f8f2005-06-23 02:26:47 +00001110 ML_(record_fd_open_nameless)(tid, fd1);
1111 ML_(record_fd_open_nameless)(tid, fd2);
sewardj9efbbef2005-03-01 16:45:23 +00001112 }
1113 }
1114 return r;
1115}
1116
1117/* ------ */
1118
sewardja8d8e232005-06-07 20:04:56 +00001119SysRes
sewardj7eb7c582005-06-23 01:02:53 +00001120ML_(generic_POST_sys_socket) ( ThreadId tid, SysRes res )
sewardj9efbbef2005-03-01 16:45:23 +00001121{
sewardja8d8e232005-06-07 20:04:56 +00001122 SysRes r = res;
1123 vg_assert(!res.isError); /* guaranteed by caller */
sewardj7eb7c582005-06-23 01:02:53 +00001124 if (!ML_(fd_allowed)(res.val, "socket", tid, True)) {
sewardja8d8e232005-06-07 20:04:56 +00001125 VG_(close)(res.val);
1126 r = VG_(mk_SysRes_Error)( VKI_EMFILE );
sewardj9efbbef2005-03-01 16:45:23 +00001127 } else {
1128 if (VG_(clo_track_fds))
njnf845f8f2005-06-23 02:26:47 +00001129 ML_(record_fd_open_nameless)(tid, res.val);
sewardj9efbbef2005-03-01 16:45:23 +00001130 }
1131 return r;
1132}
1133
1134/* ------ */
1135
sewardj987a8eb2005-03-01 19:00:30 +00001136void
sewardj7eb7c582005-06-23 01:02:53 +00001137ML_(generic_PRE_sys_bind) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001138 UWord arg0, UWord arg1, UWord arg2 )
1139{
1140 /* int bind(int sockfd, struct sockaddr *my_addr,
1141 int addrlen); */
1142 pre_mem_read_sockaddr(
1143 tid, "socketcall.bind(my_addr.%s)",
1144 (struct vki_sockaddr *) arg1, arg2
1145 );
1146}
1147
1148/* ------ */
1149
sewardj987a8eb2005-03-01 19:00:30 +00001150void
sewardj7eb7c582005-06-23 01:02:53 +00001151ML_(generic_PRE_sys_accept) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001152 UWord arg0, UWord arg1, UWord arg2 )
1153{
1154 /* int accept(int s, struct sockaddr *addr, int *addrlen); */
1155 Addr addr_p = arg1;
1156 Addr addrlen_p = arg2;
1157 if (addr_p != (Addr)NULL)
1158 buf_and_len_pre_check ( tid, addr_p, addrlen_p,
1159 "socketcall.accept(addr)",
1160 "socketcall.accept(addrlen_in)" );
1161}
1162
sewardja8d8e232005-06-07 20:04:56 +00001163SysRes
sewardj7eb7c582005-06-23 01:02:53 +00001164ML_(generic_POST_sys_accept) ( ThreadId tid,
sewardja8d8e232005-06-07 20:04:56 +00001165 SysRes res,
sewardj987a8eb2005-03-01 19:00:30 +00001166 UWord arg0, UWord arg1, UWord arg2 )
sewardj9efbbef2005-03-01 16:45:23 +00001167{
sewardja8d8e232005-06-07 20:04:56 +00001168 SysRes r = res;
1169 vg_assert(!res.isError); /* guaranteed by caller */
sewardj7eb7c582005-06-23 01:02:53 +00001170 if (!ML_(fd_allowed)(res.val, "accept", tid, True)) {
sewardja8d8e232005-06-07 20:04:56 +00001171 VG_(close)(res.val);
1172 r = VG_(mk_SysRes_Error)( VKI_EMFILE );
sewardj9efbbef2005-03-01 16:45:23 +00001173 } else {
1174 Addr addr_p = arg1;
1175 Addr addrlen_p = arg2;
1176 if (addr_p != (Addr)NULL)
1177 buf_and_len_post_check ( tid, res, addr_p, addrlen_p,
1178 "socketcall.accept(addrlen_out)" );
1179 if (VG_(clo_track_fds))
njnf845f8f2005-06-23 02:26:47 +00001180 ML_(record_fd_open_nameless)(tid, res.val);
sewardj9efbbef2005-03-01 16:45:23 +00001181 }
1182 return r;
1183}
1184
1185/* ------ */
1186
sewardj987a8eb2005-03-01 19:00:30 +00001187void
sewardj7eb7c582005-06-23 01:02:53 +00001188ML_(generic_PRE_sys_sendto) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001189 UWord arg0, UWord arg1, UWord arg2,
1190 UWord arg3, UWord arg4, UWord arg5 )
1191{
1192 /* int sendto(int s, const void *msg, int len,
1193 unsigned int flags,
1194 const struct sockaddr *to, int tolen); */
1195 PRE_MEM_READ( "socketcall.sendto(msg)",
1196 arg1, /* msg */
1197 arg2 /* len */ );
1198 pre_mem_read_sockaddr(
1199 tid, "socketcall.sendto(to.%s)",
1200 (struct vki_sockaddr *) arg4, arg5
1201 );
1202}
1203
1204/* ------ */
1205
sewardj987a8eb2005-03-01 19:00:30 +00001206void
sewardj7eb7c582005-06-23 01:02:53 +00001207ML_(generic_PRE_sys_send) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001208 UWord arg0, UWord arg1, UWord arg2 )
1209{
1210 /* int send(int s, const void *msg, size_t len, int flags); */
1211 PRE_MEM_READ( "socketcall.send(msg)",
1212 arg1, /* msg */
1213 arg2 /* len */ );
1214
1215}
1216
1217/* ------ */
1218
sewardj987a8eb2005-03-01 19:00:30 +00001219void
sewardj7eb7c582005-06-23 01:02:53 +00001220ML_(generic_PRE_sys_recvfrom) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001221 UWord arg0, UWord arg1, UWord arg2,
1222 UWord arg3, UWord arg4, UWord arg5 )
1223{
1224 /* int recvfrom(int s, void *buf, int len, unsigned int flags,
1225 struct sockaddr *from, int *fromlen); */
1226 Addr buf_p = arg1;
1227 Int len = arg2;
1228 Addr from_p = arg4;
1229 Addr fromlen_p = arg5;
1230 PRE_MEM_WRITE( "socketcall.recvfrom(buf)", buf_p, len );
1231 if (from_p != (Addr)NULL)
1232 buf_and_len_pre_check ( tid, from_p, fromlen_p,
1233 "socketcall.recvfrom(from)",
1234 "socketcall.recvfrom(fromlen_in)" );
1235}
1236
sewardj987a8eb2005-03-01 19:00:30 +00001237void
sewardj7eb7c582005-06-23 01:02:53 +00001238ML_(generic_POST_sys_recvfrom) ( ThreadId tid,
sewardja8d8e232005-06-07 20:04:56 +00001239 SysRes res,
sewardj9efbbef2005-03-01 16:45:23 +00001240 UWord arg0, UWord arg1, UWord arg2,
1241 UWord arg3, UWord arg4, UWord arg5 )
1242{
1243 Addr buf_p = arg1;
1244 Int len = arg2;
1245 Addr from_p = arg4;
1246 Addr fromlen_p = arg5;
1247
sewardja8d8e232005-06-07 20:04:56 +00001248 vg_assert(!res.isError); /* guaranteed by caller */
sewardj9efbbef2005-03-01 16:45:23 +00001249 if (from_p != (Addr)NULL)
1250 buf_and_len_post_check ( tid, res, from_p, fromlen_p,
1251 "socketcall.recvfrom(fromlen_out)" );
1252 POST_MEM_WRITE( buf_p, len );
1253}
1254
1255/* ------ */
1256
sewardj987a8eb2005-03-01 19:00:30 +00001257void
sewardj7eb7c582005-06-23 01:02:53 +00001258ML_(generic_PRE_sys_recv) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001259 UWord arg0, UWord arg1, UWord arg2 )
1260{
1261 /* int recv(int s, void *buf, int len, unsigned int flags); */
1262 /* man 2 recv says:
1263 The recv call is normally used only on a connected socket
1264 (see connect(2)) and is identical to recvfrom with a NULL
1265 from parameter.
1266 */
1267 PRE_MEM_WRITE( "socketcall.recv(buf)",
1268 arg1, /* buf */
1269 arg2 /* len */ );
1270}
1271
sewardj987a8eb2005-03-01 19:00:30 +00001272void
sewardj7eb7c582005-06-23 01:02:53 +00001273ML_(generic_POST_sys_recv) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001274 UWord res,
1275 UWord arg0, UWord arg1, UWord arg2 )
1276{
1277 if (res >= 0 && arg1 != 0) {
1278 POST_MEM_WRITE( arg1, /* buf */
1279 arg2 /* len */ );
1280 }
1281}
1282
1283/* ------ */
1284
sewardj987a8eb2005-03-01 19:00:30 +00001285void
sewardj7eb7c582005-06-23 01:02:53 +00001286ML_(generic_PRE_sys_connect) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001287 UWord arg0, UWord arg1, UWord arg2 )
1288{
1289 /* int connect(int sockfd,
1290 struct sockaddr *serv_addr, int addrlen ); */
1291 PRE_MEM_READ( "socketcall.connect(serv_addr.sa_family)",
1292 arg1, /* serv_addr */
1293 sizeof(vki_sa_family_t));
1294 pre_mem_read_sockaddr( tid,
1295 "socketcall.connect(serv_addr.%s)",
1296 (struct vki_sockaddr *) arg1, arg2);
1297}
1298
1299/* ------ */
1300
sewardj987a8eb2005-03-01 19:00:30 +00001301void
sewardj7eb7c582005-06-23 01:02:53 +00001302ML_(generic_PRE_sys_setsockopt) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001303 UWord arg0, UWord arg1, UWord arg2,
1304 UWord arg3, UWord arg4 )
1305{
1306 /* int setsockopt(int s, int level, int optname,
1307 const void *optval, int optlen); */
1308 PRE_MEM_READ( "socketcall.setsockopt(optval)",
1309 arg3, /* optval */
1310 arg4 /* optlen */ );
1311}
1312
1313/* ------ */
1314
sewardj987a8eb2005-03-01 19:00:30 +00001315void
sewardj7eb7c582005-06-23 01:02:53 +00001316ML_(generic_PRE_sys_getsockopt) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001317 UWord arg0, UWord arg1, UWord arg2,
1318 UWord arg3, UWord arg4 )
1319{
1320 /* int getsockopt(int s, int level, int optname,
1321 void *optval, socklen_t *optlen); */
1322 Addr optval_p = arg3;
1323 Addr optlen_p = arg4;
1324 /* vg_assert(sizeof(socklen_t) == sizeof(UInt)); */
tom1aa57372005-08-28 10:16:29 +00001325 if (optval_p != (Addr)NULL) {
sewardj9efbbef2005-03-01 16:45:23 +00001326 buf_and_len_pre_check ( tid, optval_p, optlen_p,
1327 "socketcall.getsockopt(optval)",
1328 "socketcall.getsockopt(optlen)" );
tom1aa57372005-08-28 10:16:29 +00001329 if (arg1 == VKI_SOL_SCTP &&
1330 (arg2 == VKI_SCTP_GET_PEER_ADDRS || arg2 == VKI_SCTP_GET_LOCAL_ADDRS)) {
1331 struct vki_sctp_getaddrs *ga = (struct vki_sctp_getaddrs*)arg3;
1332 int address_bytes = sizeof(struct vki_sockaddr_in6) * ga->addr_num;
1333 PRE_MEM_WRITE( "socketcall.getsockopt(optval.addrs)", (Addr)ga->addrs, address_bytes );
1334 }
1335 }
sewardj9efbbef2005-03-01 16:45:23 +00001336}
1337
sewardj987a8eb2005-03-01 19:00:30 +00001338void
sewardj7eb7c582005-06-23 01:02:53 +00001339ML_(generic_POST_sys_getsockopt) ( ThreadId tid,
sewardja8d8e232005-06-07 20:04:56 +00001340 SysRes res,
sewardj9efbbef2005-03-01 16:45:23 +00001341 UWord arg0, UWord arg1, UWord arg2,
1342 UWord arg3, UWord arg4 )
1343{
1344 Addr optval_p = arg3;
1345 Addr optlen_p = arg4;
sewardja8d8e232005-06-07 20:04:56 +00001346 vg_assert(!res.isError); /* guaranteed by caller */
tom1aa57372005-08-28 10:16:29 +00001347 if (optval_p != (Addr)NULL) {
sewardj9efbbef2005-03-01 16:45:23 +00001348 buf_and_len_post_check ( tid, res, optval_p, optlen_p,
1349 "socketcall.getsockopt(optlen_out)" );
tom1aa57372005-08-28 10:16:29 +00001350 if (arg1 == VKI_SOL_SCTP &&
1351 (arg2 == VKI_SCTP_GET_PEER_ADDRS || arg2 == VKI_SCTP_GET_LOCAL_ADDRS)) {
1352 struct vki_sctp_getaddrs *ga = (struct vki_sctp_getaddrs*)arg3;
1353 struct vki_sockaddr *a = ga->addrs;
1354 int i;
1355 for (i = 0; i < ga->addr_num; i++) {
1356 int sl = 0;
1357 if (a->sa_family == VKI_AF_INET)
1358 sl = sizeof(struct vki_sockaddr_in);
1359 else if (a->sa_family == VKI_AF_INET6)
1360 sl = sizeof(struct vki_sockaddr_in6);
1361 else {
1362 VG_(message)(Vg_UserMsg, "Warning: getsockopt: unhandled address type %d", a->sa_family);
1363 }
1364 a = (struct vki_sockaddr*)((char*)a + sl);
1365 }
1366 POST_MEM_WRITE( (Addr)ga->addrs, (char*)a - (char*)ga->addrs );
1367 }
1368 }
sewardj9efbbef2005-03-01 16:45:23 +00001369}
1370
1371/* ------ */
1372
sewardj987a8eb2005-03-01 19:00:30 +00001373void
sewardj7eb7c582005-06-23 01:02:53 +00001374ML_(generic_PRE_sys_getsockname) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001375 UWord arg0, UWord arg1, UWord arg2 )
1376{
1377 /* int getsockname(int s, struct sockaddr* name, int* namelen) */
1378 Addr name_p = arg1;
1379 Addr namelen_p = arg2;
1380 /* Nb: name_p cannot be NULL */
1381 buf_and_len_pre_check ( tid, name_p, namelen_p,
1382 "socketcall.getsockname(name)",
1383 "socketcall.getsockname(namelen_in)" );
1384}
1385
sewardj987a8eb2005-03-01 19:00:30 +00001386void
sewardj7eb7c582005-06-23 01:02:53 +00001387ML_(generic_POST_sys_getsockname) ( ThreadId tid,
sewardja8d8e232005-06-07 20:04:56 +00001388 SysRes res,
sewardj9efbbef2005-03-01 16:45:23 +00001389 UWord arg0, UWord arg1, UWord arg2 )
1390{
1391 Addr name_p = arg1;
1392 Addr namelen_p = arg2;
sewardja8d8e232005-06-07 20:04:56 +00001393 vg_assert(!res.isError); /* guaranteed by caller */
sewardj9efbbef2005-03-01 16:45:23 +00001394 buf_and_len_post_check ( tid, res, name_p, namelen_p,
1395 "socketcall.getsockname(namelen_out)" );
1396}
1397
1398/* ------ */
1399
sewardj987a8eb2005-03-01 19:00:30 +00001400void
sewardj7eb7c582005-06-23 01:02:53 +00001401ML_(generic_PRE_sys_getpeername) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001402 UWord arg0, UWord arg1, UWord arg2 )
1403{
1404 /* int getpeername(int s, struct sockaddr* name, int* namelen) */
1405 Addr name_p = arg1;
1406 Addr namelen_p = arg2;
1407 /* Nb: name_p cannot be NULL */
1408 buf_and_len_pre_check ( tid, name_p, namelen_p,
1409 "socketcall.getpeername(name)",
1410 "socketcall.getpeername(namelen_in)" );
1411}
1412
sewardj987a8eb2005-03-01 19:00:30 +00001413void
sewardj7eb7c582005-06-23 01:02:53 +00001414ML_(generic_POST_sys_getpeername) ( ThreadId tid,
sewardja8d8e232005-06-07 20:04:56 +00001415 SysRes res,
sewardj9efbbef2005-03-01 16:45:23 +00001416 UWord arg0, UWord arg1, UWord arg2 )
1417{
1418 Addr name_p = arg1;
1419 Addr namelen_p = arg2;
sewardja8d8e232005-06-07 20:04:56 +00001420 vg_assert(!res.isError); /* guaranteed by caller */
sewardj9efbbef2005-03-01 16:45:23 +00001421 buf_and_len_post_check ( tid, res, name_p, namelen_p,
1422 "socketcall.getpeername(namelen_out)" );
1423}
1424
1425/* ------ */
1426
sewardj987a8eb2005-03-01 19:00:30 +00001427void
sewardj7eb7c582005-06-23 01:02:53 +00001428ML_(generic_PRE_sys_sendmsg) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001429 UWord arg0, UWord arg1 )
1430{
1431 /* int sendmsg(int s, const struct msghdr *msg, int flags); */
1432 struct vki_msghdr *msg = (struct vki_msghdr *)arg1;
1433 msghdr_foreachfield ( tid, msg, pre_mem_read_sendmsg );
1434}
1435
1436/* ------ */
1437
sewardj987a8eb2005-03-01 19:00:30 +00001438void
sewardj7eb7c582005-06-23 01:02:53 +00001439ML_(generic_PRE_sys_recvmsg) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001440 UWord arg0, UWord arg1 )
1441{
1442 /* int recvmsg(int s, struct msghdr *msg, int flags); */
1443 struct vki_msghdr *msg = (struct vki_msghdr *)arg1;
1444 msghdr_foreachfield ( tid, msg, pre_mem_write_recvmsg );
1445}
1446
sewardj987a8eb2005-03-01 19:00:30 +00001447void
sewardj7eb7c582005-06-23 01:02:53 +00001448ML_(generic_POST_sys_recvmsg) ( ThreadId tid,
sewardj9efbbef2005-03-01 16:45:23 +00001449 UWord arg0, UWord arg1 )
1450{
1451 struct vki_msghdr *msg = (struct vki_msghdr *)arg1;
1452 msghdr_foreachfield( tid, msg, post_mem_write_recvmsg );
1453 check_cmsg_for_fds( tid, msg );
1454}
1455
1456
1457/* ---------------------------------------------------------------------
sewardjb369c5e2005-03-24 17:52:02 +00001458 Deal with a bunch of IPC related syscalls
1459 ------------------------------------------------------------------ */
1460
1461/* ------ */
1462
1463void
sewardj7eb7c582005-06-23 01:02:53 +00001464ML_(generic_PRE_sys_semop) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001465 UWord arg0, UWord arg1, UWord arg2 )
1466{
1467 /* int semop(int semid, struct sembuf *sops, unsigned nsops); */
1468 PRE_MEM_READ( "semop(sops)", arg1, arg2 * sizeof(struct vki_sembuf) );
1469}
1470
1471/* ------ */
1472
1473void
sewardj7eb7c582005-06-23 01:02:53 +00001474ML_(generic_PRE_sys_semtimedop) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001475 UWord arg0, UWord arg1,
1476 UWord arg2, UWord arg3 )
1477{
1478 /* int semtimedop(int semid, struct sembuf *sops, unsigned nsops,
1479 struct timespec *timeout); */
1480 PRE_MEM_READ( "semtimedop(sops)", arg1, arg2 * sizeof(struct vki_sembuf) );
1481 if (arg3 != 0)
1482 PRE_MEM_READ( "semtimedop(timeout)", arg3, sizeof(struct vki_timespec) );
1483}
1484
1485/* ------ */
1486
1487static
1488UInt get_sem_count( Int semid )
1489{
sewardja8d8e232005-06-07 20:04:56 +00001490 struct vki_semid_ds buf;
1491 union vki_semun arg;
1492 SysRes res;
sewardjb369c5e2005-03-24 17:52:02 +00001493
sewardja8d8e232005-06-07 20:04:56 +00001494 arg.buf = &buf;
sewardjb369c5e2005-03-24 17:52:02 +00001495
sewardja8d8e232005-06-07 20:04:56 +00001496# ifdef __NR_semctl
1497 res = VG_(do_syscall4)(__NR_semctl, semid, 0, VKI_IPC_STAT, *(UWord *)&arg);
1498# else
1499 res = VG_(do_syscall5)(__NR_ipc, 3 /* IPCOP_semctl */, semid, 0,
1500 VKI_IPC_STAT, (UWord)&arg);
1501# endif
1502 if (res.isError)
1503 return 0;
sewardjb369c5e2005-03-24 17:52:02 +00001504
sewardja8d8e232005-06-07 20:04:56 +00001505 return buf.sem_nsems;
sewardjb369c5e2005-03-24 17:52:02 +00001506}
1507
1508void
sewardj7eb7c582005-06-23 01:02:53 +00001509ML_(generic_PRE_sys_semctl) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001510 UWord arg0, UWord arg1,
1511 UWord arg2, UWord arg3 )
1512{
1513 /* int semctl(int semid, int semnum, int cmd, ...); */
1514 union vki_semun arg = *(union vki_semun *)&arg3;
1515 UInt nsems;
1516 switch (arg2 /* cmd */) {
1517 case VKI_IPC_INFO:
1518 case VKI_SEM_INFO:
1519 case VKI_IPC_INFO|VKI_IPC_64:
1520 case VKI_SEM_INFO|VKI_IPC_64:
1521 PRE_MEM_WRITE( "semctl(IPC_INFO, arg.buf)",
1522 (Addr)arg.buf, sizeof(struct vki_seminfo) );
1523 break;
1524 case VKI_IPC_STAT:
1525 case VKI_SEM_STAT:
1526 PRE_MEM_WRITE( "semctl(IPC_STAT, arg.buf)",
1527 (Addr)arg.buf, sizeof(struct vki_semid_ds) );
1528 break;
1529 case VKI_IPC_STAT|VKI_IPC_64:
1530 case VKI_SEM_STAT|VKI_IPC_64:
1531 PRE_MEM_WRITE( "semctl(IPC_STAT, arg.buf)",
1532 (Addr)arg.buf, sizeof(struct vki_semid64_ds) );
1533 break;
1534 case VKI_IPC_SET:
1535 PRE_MEM_READ( "semctl(IPC_SET, arg.buf)",
1536 (Addr)arg.buf, sizeof(struct vki_semid_ds) );
1537 break;
1538 case VKI_IPC_SET|VKI_IPC_64:
1539 PRE_MEM_READ( "semctl(IPC_SET, arg.buf)",
1540 (Addr)arg.buf, sizeof(struct vki_semid64_ds) );
1541 break;
1542 case VKI_GETALL:
1543 case VKI_GETALL|VKI_IPC_64:
1544 nsems = get_sem_count( arg0 );
1545 PRE_MEM_WRITE( "semctl(IPC_GETALL, arg.array)",
1546 (Addr)arg.array, sizeof(unsigned short) * nsems );
1547 break;
1548 case VKI_SETALL:
1549 case VKI_SETALL|VKI_IPC_64:
1550 nsems = get_sem_count( arg0 );
1551 PRE_MEM_READ( "semctl(IPC_SETALL, arg.array)",
1552 (Addr)arg.array, sizeof(unsigned short) * nsems );
1553 break;
1554 }
1555}
1556
1557void
sewardj7eb7c582005-06-23 01:02:53 +00001558ML_(generic_POST_sys_semctl) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001559 UWord res,
1560 UWord arg0, UWord arg1,
1561 UWord arg2, UWord arg3 )
1562{
1563 union vki_semun arg = *(union vki_semun *)&arg3;
1564 UInt nsems;
1565 switch (arg2 /* cmd */) {
1566 case VKI_IPC_INFO:
1567 case VKI_SEM_INFO:
1568 case VKI_IPC_INFO|VKI_IPC_64:
1569 case VKI_SEM_INFO|VKI_IPC_64:
1570 POST_MEM_WRITE( (Addr)arg.buf, sizeof(struct vki_seminfo) );
1571 break;
1572 case VKI_IPC_STAT:
1573 case VKI_SEM_STAT:
1574 POST_MEM_WRITE( (Addr)arg.buf, sizeof(struct vki_semid_ds) );
1575 break;
1576 case VKI_IPC_STAT|VKI_IPC_64:
1577 case VKI_SEM_STAT|VKI_IPC_64:
1578 POST_MEM_WRITE( (Addr)arg.buf, sizeof(struct vki_semid64_ds) );
1579 break;
1580 case VKI_GETALL:
1581 case VKI_GETALL|VKI_IPC_64:
1582 nsems = get_sem_count( arg0 );
1583 POST_MEM_WRITE( (Addr)arg.array, sizeof(unsigned short) * nsems );
1584 break;
1585 }
1586}
1587
1588/* ------ */
1589
sewardjb369c5e2005-03-24 17:52:02 +00001590/* ------ */
1591
1592static
1593UInt get_shm_size ( Int shmid )
1594{
sewardja8d8e232005-06-07 20:04:56 +00001595# ifdef __NR_shmctl
sewardjb369c5e2005-03-24 17:52:02 +00001596 struct vki_shmid64_ds buf;
sewardja8d8e232005-06-07 20:04:56 +00001597 SysRes __res = VG_(do_syscall3)(__NR_shmctl, shmid, VKI_IPC_STAT, (UWord)&buf);
1598# else
sewardjb369c5e2005-03-24 17:52:02 +00001599 struct vki_shmid_ds buf;
sewardja8d8e232005-06-07 20:04:56 +00001600 SysRes __res = VG_(do_syscall5)(__NR_ipc, 24 /* IPCOP_shmctl */, shmid,
sewardjb369c5e2005-03-24 17:52:02 +00001601 VKI_IPC_STAT, 0, (UWord)&buf);
sewardja8d8e232005-06-07 20:04:56 +00001602# endif
1603 if (__res.isError)
sewardjb369c5e2005-03-24 17:52:02 +00001604 return 0;
1605
1606 return buf.shm_segsz;
1607}
1608
1609UWord
sewardj7eb7c582005-06-23 01:02:53 +00001610ML_(generic_PRE_sys_shmat) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001611 UWord arg0, UWord arg1, UWord arg2 )
1612{
1613 /* void *shmat(int shmid, const void *shmaddr, int shmflg); */
sewardj45f4e7c2005-09-27 19:20:21 +00001614 UInt segmentSize = get_shm_size ( arg0 );
1615 UWord tmp;
1616 Bool ok;
1617 if (arg1 == 0) {
1618 tmp = VG_(am_get_advisory_client_simple)(0, segmentSize, &ok);
1619 if (ok)
1620 arg1 = tmp;
1621 }
sewardj7eb7c582005-06-23 01:02:53 +00001622 else if (!ML_(valid_client_addr)(arg1, segmentSize, tid, "shmat"))
sewardjb369c5e2005-03-24 17:52:02 +00001623 arg1 = 0;
1624 return arg1;
1625}
1626
1627void
sewardj7eb7c582005-06-23 01:02:53 +00001628ML_(generic_POST_sys_shmat) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001629 UWord res,
1630 UWord arg0, UWord arg1, UWord arg2 )
1631{
1632 UInt segmentSize = get_shm_size ( arg0 );
1633 if ( segmentSize > 0 ) {
1634 UInt prot = VKI_PROT_READ|VKI_PROT_WRITE;
sewardj45f4e7c2005-09-27 19:20:21 +00001635 Bool d;
sewardjb369c5e2005-03-24 17:52:02 +00001636
tomf61fea02005-10-04 12:04:06 +00001637 if (arg2 & VKI_SHM_RDONLY)
sewardjb369c5e2005-03-24 17:52:02 +00001638 prot &= ~VKI_PROT_WRITE;
sewardj45f4e7c2005-09-27 19:20:21 +00001639 /* It isn't exactly correct to pass 0 for the fd and offset
1640 here. The kernel seems to think the corresponding section
1641 does have dev/ino numbers:
1642
1643 04e52000-04ec8000 rw-s 00000000 00:06 1966090 /SYSV00000000 (deleted)
1644
1645 However there is no obvious way to find them. In order to
1646 cope with the discrepancy, aspacem's sync checker omits the
1647 dev/ino correspondence check in cases where V does not know
1648 the dev/ino. */
tom1340c352005-10-04 15:59:54 +00001649 d = VG_(am_notify_client_shmat)( res, VG_PGROUNDUP(segmentSize), prot );
sewardj45f4e7c2005-09-27 19:20:21 +00001650
1651 /* we don't distinguish whether it's read-only or
1652 * read-write -- it doesn't matter really. */
1653 VG_TRACK( new_mem_mmap, res, segmentSize, True, True, False );
1654 if (d)
1655 VG_(discard_translations)( (Addr64)res,
1656 (ULong)VG_PGROUNDUP(segmentSize),
1657 "ML_(generic_POST_sys_shmat)" );
sewardjb369c5e2005-03-24 17:52:02 +00001658 }
1659}
1660
1661/* ------ */
1662
1663Bool
sewardj7eb7c582005-06-23 01:02:53 +00001664ML_(generic_PRE_sys_shmdt) ( ThreadId tid, UWord arg0 )
sewardjb369c5e2005-03-24 17:52:02 +00001665{
1666 /* int shmdt(const void *shmaddr); */
sewardj7eb7c582005-06-23 01:02:53 +00001667 return ML_(valid_client_addr)(arg0, 1, tid, "shmdt");
sewardjb369c5e2005-03-24 17:52:02 +00001668}
1669
1670void
sewardj7eb7c582005-06-23 01:02:53 +00001671ML_(generic_POST_sys_shmdt) ( ThreadId tid, UWord res, UWord arg0 )
sewardjb369c5e2005-03-24 17:52:02 +00001672{
sewardj45f4e7c2005-09-27 19:20:21 +00001673 NSegment* s = VG_(am_find_nsegment)(arg0);
sewardjb369c5e2005-03-24 17:52:02 +00001674
sewardj0e682c62005-09-28 20:05:31 +00001675 if (s != NULL) {
1676 Addr s_start = s->start;
1677 SizeT s_len = s->end+1 - s->start;
tom1340c352005-10-04 15:59:54 +00001678 Bool d;
1679
1680 vg_assert(s->kind == SkShmC && s->start == arg0);
1681
1682 d = VG_(am_notify_munmap)(s_start, s_len);
sewardj0e682c62005-09-28 20:05:31 +00001683 s = NULL; /* s is now invalid */
1684 VG_TRACK( die_mem_munmap, s_start, s_len );
sewardj45f4e7c2005-09-27 19:20:21 +00001685 if (d)
sewardj0e682c62005-09-28 20:05:31 +00001686 VG_(discard_translations)( (Addr64)s_start,
1687 (ULong)s_len,
sewardj45f4e7c2005-09-27 19:20:21 +00001688 "ML_(generic_POST_sys_shmdt)" );
sewardjb369c5e2005-03-24 17:52:02 +00001689 }
1690}
1691/* ------ */
1692
1693void
sewardj7eb7c582005-06-23 01:02:53 +00001694ML_(generic_PRE_sys_shmctl) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001695 UWord arg0, UWord arg1, UWord arg2 )
1696{
1697 /* int shmctl(int shmid, int cmd, struct shmid_ds *buf); */
1698 switch (arg1 /* cmd */) {
1699 case VKI_IPC_INFO:
1700 PRE_MEM_WRITE( "shmctl(IPC_INFO, buf)",
1701 arg2, sizeof(struct vki_shminfo) );
1702 break;
1703 case VKI_IPC_INFO|VKI_IPC_64:
1704 PRE_MEM_WRITE( "shmctl(IPC_INFO, buf)",
1705 arg2, sizeof(struct vki_shminfo64) );
1706 break;
1707 case VKI_SHM_INFO:
1708 case VKI_SHM_INFO|VKI_IPC_64:
1709 PRE_MEM_WRITE( "shmctl(SHM_INFO, buf)",
1710 arg2, sizeof(struct vki_shm_info) );
1711 break;
1712 case VKI_IPC_STAT:
1713 case VKI_SHM_STAT:
1714 PRE_MEM_WRITE( "shmctl(IPC_STAT, buf)",
1715 arg2, sizeof(struct vki_shmid_ds) );
1716 break;
1717 case VKI_IPC_STAT|VKI_IPC_64:
1718 case VKI_SHM_STAT|VKI_IPC_64:
1719 PRE_MEM_WRITE( "shmctl(IPC_STAT, arg.buf)",
1720 arg2, sizeof(struct vki_shmid64_ds) );
1721 break;
1722 case VKI_IPC_SET:
1723 PRE_MEM_READ( "shmctl(IPC_SET, arg.buf)",
1724 arg2, sizeof(struct vki_shmid_ds) );
1725 break;
1726 case VKI_IPC_SET|VKI_IPC_64:
1727 PRE_MEM_READ( "shmctl(IPC_SET, arg.buf)",
1728 arg2, sizeof(struct vki_shmid64_ds) );
1729 break;
1730 }
1731}
1732
1733void
sewardj7eb7c582005-06-23 01:02:53 +00001734ML_(generic_POST_sys_shmctl) ( ThreadId tid,
sewardjb369c5e2005-03-24 17:52:02 +00001735 UWord res,
1736 UWord arg0, UWord arg1, UWord arg2 )
1737{
1738 switch (arg1 /* cmd */) {
1739 case VKI_IPC_INFO:
1740 POST_MEM_WRITE( arg2, sizeof(struct vki_shminfo) );
1741 break;
1742 case VKI_IPC_INFO|VKI_IPC_64:
1743 POST_MEM_WRITE( arg2, sizeof(struct vki_shminfo64) );
1744 break;
1745 case VKI_SHM_INFO:
1746 case VKI_SHM_INFO|VKI_IPC_64:
1747 POST_MEM_WRITE( arg2, sizeof(struct vki_shm_info) );
1748 break;
1749 case VKI_IPC_STAT:
1750 case VKI_SHM_STAT:
1751 POST_MEM_WRITE( arg2, sizeof(struct vki_shmid_ds) );
1752 break;
1753 case VKI_IPC_STAT|VKI_IPC_64:
1754 case VKI_SHM_STAT|VKI_IPC_64:
1755 POST_MEM_WRITE( arg2, sizeof(struct vki_shmid64_ds) );
1756 break;
1757 }
1758}
1759
1760
1761/* ---------------------------------------------------------------------
tom9548a162005-09-30 08:07:53 +00001762 Generic handler for mmap
1763 ------------------------------------------------------------------ */
1764
tom6d85b042005-09-30 16:09:12 +00001765/*
1766 * Although mmap is specified by POSIX and the argument are generally
1767 * consistent across platforms the precise details of the low level
1768 * argument passing conventions differ. For example:
1769 *
1770 * - On x86-linux there is mmap (aka old_mmap) which takes the
1771 * arguments in a memory block and the offset in bytes; and
1772 * mmap2 (aka sys_mmap2) which takes the arguments in the normal
1773 * way and the offset in pages.
1774 *
1775 * - On ppc32-linux there is mmap (aka sys_mmap) which takes the
1776 * arguments in the normal way and the offset in bytes; and
1777 * mmap2 (aka sys_mmap2) which takes the arguments in the normal
1778 * way and the offset in pages.
1779 *
1780 * - On amd64-linux everything is simple and there is just the one
1781 * call, mmap (aka sys_mmap) which takes the arguments in the
1782 * normal way and the offset in bytes.
1783 *
1784 * To cope with all this we provide a generic handler function here
1785 * and then each platform implements one or more system call handlers
1786 * which call this generic routine after extracting and normalising
1787 * the arguments.
1788 */
1789
tom9548a162005-09-30 08:07:53 +00001790SysRes
1791ML_(generic_PRE_sys_mmap) ( ThreadId tid,
1792 UWord arg1, UWord arg2, UWord arg3,
sewardj274461d2005-10-02 17:01:41 +00001793 UWord arg4, UWord arg5, Off64T arg6 )
tom9548a162005-09-30 08:07:53 +00001794{
1795 Addr advised;
1796 SysRes sres;
1797 MapRequest mreq;
1798 Bool mreq_ok;
1799
1800 if (arg2 == 0) {
1801 /* SuSV3 says: If len is zero, mmap() shall fail and no mapping
1802 shall be established. */
1803 return VG_(mk_SysRes_Error)( VKI_EINVAL );
1804 }
1805
1806 if (!VG_IS_PAGE_ALIGNED(arg1)) {
1807 /* zap any misaligned addresses. */
1808 /* SuSV3 says misaligned addresses only cause the MAP_FIXED case
1809 to fail. Here, we catch them all. */
1810 return VG_(mk_SysRes_Error)( VKI_EINVAL );
1811 }
1812
sewardj7e21df82005-09-30 10:48:27 +00001813 if (!VG_IS_PAGE_ALIGNED(arg6)) {
1814 /* zap any misaligned offsets. */
1815 /* SuSV3 says: The off argument is constrained to be aligned and
1816 sized according to the value returned by sysconf() when
1817 passed _SC_PAGESIZE or _SC_PAGE_SIZE. */
1818 return VG_(mk_SysRes_Error)( VKI_EINVAL );
1819 }
1820
tom9548a162005-09-30 08:07:53 +00001821 /* Figure out what kind of allocation constraints there are
1822 (fixed/hint/any), and ask aspacem what we should do. */
1823 mreq.start = arg1;
1824 mreq.len = arg2;
1825 if (arg4 & VKI_MAP_FIXED) {
1826 mreq.rkind = MFixed;
1827 } else
1828 if (arg1 != 0) {
1829 mreq.rkind = MHint;
1830 } else {
1831 mreq.rkind = MAny;
1832 }
1833
1834 /* Enquire ... */
1835 advised = VG_(am_get_advisory)( &mreq, True/*client*/, &mreq_ok );
1836 if (!mreq_ok) {
1837 /* Our request was bounced, so we'd better fail. */
1838 return VG_(mk_SysRes_Error)( VKI_EINVAL );
1839 }
1840
1841 /* Otherwise we're OK (so far). Install aspacem's choice of
1842 address, and let the mmap go through. */
1843 sres = VG_(am_do_mmap_NO_NOTIFY)(advised, arg2, arg3,
1844 arg4 | VKI_MAP_FIXED,
1845 arg5, arg6);
1846
1847 if (!sres.isError) {
1848 /* Notify aspacem and the tool. */
1849 ML_(notify_aspacem_and_tool_of_mmap)(
1850 (Addr)sres.val, /* addr kernel actually assigned */
1851 arg2, arg3,
1852 arg4, /* the original flags value */
1853 arg5, arg6
1854 );
1855 /* Load symbols? */
sewardjf72cced2005-11-08 00:45:47 +00001856 VG_(di_notify_mmap)( (Addr)sres.val, False/*allow_SkFileV*/ );
tom9548a162005-09-30 08:07:53 +00001857 }
1858
1859 /* Stay sane */
1860 if (!sres.isError && (arg4 & VKI_MAP_FIXED))
1861 vg_assert(sres.val == arg1);
1862
1863 return sres;
1864}
1865
1866
1867/* ---------------------------------------------------------------------
nethercote4fa681f2004-11-08 17:51:39 +00001868 The Main Entertainment ... syscall wrappers
njn25e49d8e72002-09-23 09:36:25 +00001869 ------------------------------------------------------------------ */
sewardjde4a1d02002-03-22 01:27:54 +00001870
nethercote4fa681f2004-11-08 17:51:39 +00001871/* Note: the PRE() and POST() wrappers are for the actual functions
nethercote8ff888f2004-11-17 17:11:45 +00001872 implementing the system calls in the OS kernel. These mostly have
nethercote4fa681f2004-11-08 17:51:39 +00001873 names like sys_write(); a few have names like old_mmap(). See the
njnaf839f52005-06-23 03:27:57 +00001874 comment for ML_(syscall_table)[] for important info about the __NR_foo
nethercote8ff888f2004-11-17 17:11:45 +00001875 constants and their relationship to the sys_foo() functions.
nethercote4fa681f2004-11-08 17:51:39 +00001876
nethercote92b2fd52004-11-16 16:15:41 +00001877 Some notes about names used for syscalls and args:
1878 - For the --trace-syscalls=yes output, we use the sys_foo() name to avoid
1879 ambiguity.
1880
1881 - For error messages, we generally use a somewhat generic name
1882 for the syscall (eg. "write" rather than "sys_write"). This should be
1883 good enough for the average user to understand what is happening,
1884 without confusing them with names like "sys_write".
1885
1886 - Also, for error messages the arg names are mostly taken from the man
1887 pages (even though many of those man pages are really for glibc
nethercote8ff888f2004-11-17 17:11:45 +00001888 functions of the same name), rather than from the OS kernel source,
nethercote92b2fd52004-11-16 16:15:41 +00001889 for the same reason -- a user presented with a "bogus foo(bar)" arg
1890 will most likely look at the "foo" man page to see which is the "bar"
1891 arg.
nethercote8b76fe52004-11-08 19:20:09 +00001892
nethercote9c311eb2004-11-12 18:20:12 +00001893 Note that we use our own vki_* types. The one exception is in
1894 PRE_REG_READn calls, where pointer types haven't been changed, because
1895 they don't need to be -- eg. for "foo*" to be used, the type foo need not
1896 be visible.
1897
nethercote4fa681f2004-11-08 17:51:39 +00001898 XXX: some of these are arch-specific, and should be factored out.
1899*/
1900
sewardja8d8e232005-06-07 20:04:56 +00001901#define PRE(name) DEFN_PRE_TEMPLATE(generic, name)
1902#define POST(name) DEFN_POST_TEMPLATE(generic, name)
jsgf855d93d2003-10-13 22:26:55 +00001903
sewardje7aa4ae2005-06-09 12:43:42 +00001904// Combine two 32-bit values into a 64-bit value
1905#define LOHI64(lo,hi) ( (lo) | ((ULong)(hi) << 32) )
1906
sewardja8d8e232005-06-07 20:04:56 +00001907//zz //PRE(sys_exit_group, Special)
1908//zz //{
1909//zz // VG_(core_panic)("syscall exit_group() not caught by the scheduler?!");
1910//zz //}
nethercoteef0c7662004-11-06 15:38:43 +00001911
sewardja8d8e232005-06-07 20:04:56 +00001912PRE(sys_exit)
jsgf855d93d2003-10-13 22:26:55 +00001913{
sewardja8d8e232005-06-07 20:04:56 +00001914 ThreadState* tst;
sewardja922b612005-03-11 02:47:32 +00001915 /* simple; just make this thread exit */
1916 PRINT("exit( %d )", ARG1);
1917 PRE_REG_READ1(void, "exit", int, exitcode);
sewardja8d8e232005-06-07 20:04:56 +00001918 tst = VG_(get_ThreadState)(tid);
1919 /* Set the thread's status to be exiting, then claim that the
1920 syscall succeeded. */
sewardja922b612005-03-11 02:47:32 +00001921 tst->exitreason = VgSrc_ExitSyscall;
1922 tst->os_state.exitcode = ARG1;
sewardja8d8e232005-06-07 20:04:56 +00001923 SET_STATUS_Success(0);
jsgf855d93d2003-10-13 22:26:55 +00001924}
1925
sewardja8d8e232005-06-07 20:04:56 +00001926PRE(sys_ni_syscall)
nethercoteeb1c7b72004-11-11 19:43:50 +00001927{
1928 PRINT("non-existent syscall! (ni_syscall)");
1929 PRE_REG_READ0(long, "ni_syscall");
sewardja8d8e232005-06-07 20:04:56 +00001930 SET_STATUS_Failure( VKI_ENOSYS );
nethercoteeb1c7b72004-11-11 19:43:50 +00001931}
1932
sewardj696c5512005-06-08 23:38:32 +00001933PRE(sys_iopl)
1934{
1935 PRINT("sys_iopl ( %d )", ARG1);
1936 PRE_REG_READ1(long, "iopl", unsigned long, level);
1937}
1938
sewardje6d5e722005-06-10 10:27:55 +00001939// XXX: this wrapper is only suitable for 32-bit platforms
1940#if defined(VGP_x86_linux)
1941PRE(sys_lookup_dcookie)
1942{
1943 PRINT("sys_lookup_dcookie (0x%llx, %p, %d)", LOHI64(ARG1,ARG2), ARG3, ARG4);
1944 PRE_REG_READ4(long, "lookup_dcookie",
1945 vki_u32, cookie_low32, vki_u32, cookie_high32,
1946 char *, buf, vki_size_t, len);
1947 PRE_MEM_WRITE( "lookup_dcookie(buf)", ARG3, ARG4);
1948}
1949POST(sys_lookup_dcookie)
1950{
1951 vg_assert(SUCCESS);
1952 if (ARG3 != (Addr)NULL)
1953 POST_MEM_WRITE( ARG3, RES);
1954}
1955#endif
sewardj78b50e42005-06-08 01:47:28 +00001956
1957PRE(sys_fsync)
1958{
1959 *flags |= SfMayBlock;
1960 PRINT("sys_fsync ( %d )", ARG1);
1961 PRE_REG_READ1(long, "fsync", unsigned int, fd);
1962}
1963
sewardj696c5512005-06-08 23:38:32 +00001964PRE(sys_fdatasync)
1965{
1966 *flags |= SfMayBlock;
1967 PRINT("sys_fdatasync ( %d )", ARG1);
1968 PRE_REG_READ1(long, "fdatasync", unsigned int, fd);
1969}
1970
1971PRE(sys_msync)
1972{
1973 *flags |= SfMayBlock;
1974 PRINT("sys_msync ( %p, %llu, %d )", ARG1,(ULong)ARG2,ARG3);
1975 PRE_REG_READ3(long, "msync",
1976 unsigned long, start, vki_size_t, length, int, flags);
1977 PRE_MEM_READ( "msync(start)", ARG1, ARG2 );
1978}
1979
sewardje6d5e722005-06-10 10:27:55 +00001980// Nb: getpmsg() and putpmsg() are special additional syscalls used in early
1981// versions of LiS (Linux Streams). They are not part of the kernel.
1982// Therefore, we have to provide this type ourself, rather than getting it
1983// from the kernel sources.
1984struct vki_pmsg_strbuf {
1985 int maxlen; /* no. of bytes in buffer */
1986 int len; /* no. of bytes returned */
1987 vki_caddr_t buf; /* pointer to data */
1988};
1989PRE(sys_getpmsg)
1990{
1991 /* LiS getpmsg from http://www.gcom.com/home/linux/lis/ */
1992 struct vki_pmsg_strbuf *ctrl;
1993 struct vki_pmsg_strbuf *data;
1994 *flags |= SfMayBlock;
1995 PRINT("sys_getpmsg ( %d, %p, %p, %p, %p )", ARG1,ARG2,ARG3,ARG4,ARG5);
1996 PRE_REG_READ5(int, "getpmsg",
1997 int, fd, struct strbuf *, ctrl, struct strbuf *, data,
1998 int *, bandp, int *, flagsp);
1999 ctrl = (struct vki_pmsg_strbuf *)ARG2;
2000 data = (struct vki_pmsg_strbuf *)ARG3;
2001 if (ctrl && ctrl->maxlen > 0)
2002 PRE_MEM_WRITE( "getpmsg(ctrl)", (Addr)ctrl->buf, ctrl->maxlen);
2003 if (data && data->maxlen > 0)
2004 PRE_MEM_WRITE( "getpmsg(data)", (Addr)data->buf, data->maxlen);
2005 if (ARG4)
2006 PRE_MEM_WRITE( "getpmsg(bandp)", (Addr)ARG4, sizeof(int));
2007 if (ARG5)
2008 PRE_MEM_WRITE( "getpmsg(flagsp)", (Addr)ARG5, sizeof(int));
2009}
2010POST(sys_getpmsg)
2011{
2012 struct vki_pmsg_strbuf *ctrl;
2013 struct vki_pmsg_strbuf *data;
2014 vg_assert(SUCCESS);
2015 ctrl = (struct vki_pmsg_strbuf *)ARG2;
2016 data = (struct vki_pmsg_strbuf *)ARG3;
2017 if (RES == 0 && ctrl && ctrl->len > 0) {
2018 POST_MEM_WRITE( (Addr)ctrl->buf, ctrl->len);
2019 }
2020 if (RES == 0 && data && data->len > 0) {
2021 POST_MEM_WRITE( (Addr)data->buf, data->len);
2022 }
2023}
2024
2025PRE(sys_putpmsg)
2026{
2027 /* LiS putpmsg from http://www.gcom.com/home/linux/lis/ */
2028 struct vki_pmsg_strbuf *ctrl;
2029 struct vki_pmsg_strbuf *data;
2030 *flags |= SfMayBlock;
2031 PRINT("sys_putpmsg ( %d, %p, %p, %d, %d )", ARG1,ARG2,ARG3,ARG4,ARG5);
2032 PRE_REG_READ5(int, "putpmsg",
2033 int, fd, struct strbuf *, ctrl, struct strbuf *, data,
2034 int, band, int, flags);
2035 ctrl = (struct vki_pmsg_strbuf *)ARG2;
2036 data = (struct vki_pmsg_strbuf *)ARG3;
2037 if (ctrl && ctrl->len > 0)
2038 PRE_MEM_READ( "putpmsg(ctrl)", (Addr)ctrl->buf, ctrl->len);
2039 if (data && data->len > 0)
2040 PRE_MEM_READ( "putpmsg(data)", (Addr)data->buf, data->len);
2041}
sewardj696c5512005-06-08 23:38:32 +00002042
2043PRE(sys_getitimer)
2044{
2045 PRINT("sys_getitimer ( %d, %p )", ARG1, ARG2);
2046 PRE_REG_READ2(long, "getitimer", int, which, struct itimerval *, value);
2047 PRE_MEM_WRITE( "getitimer(value)", ARG2, sizeof(struct vki_itimerval) );
2048}
sewardj696c5512005-06-08 23:38:32 +00002049POST(sys_getitimer)
2050{
2051 if (ARG2 != (Addr)NULL) {
2052 POST_MEM_WRITE(ARG2, sizeof(struct vki_itimerval));
2053 }
2054}
2055
2056PRE(sys_setitimer)
2057{
2058 PRINT("sys_setitimer ( %d, %p, %p )", ARG1,ARG2,ARG3);
2059 PRE_REG_READ3(long, "setitimer",
2060 int, which,
2061 struct itimerval *, value, struct itimerval *, ovalue);
2062 if (ARG2 != (Addr)NULL)
2063 PRE_MEM_READ( "setitimer(value)", ARG2, sizeof(struct vki_itimerval) );
2064 if (ARG3 != (Addr)NULL)
2065 PRE_MEM_WRITE( "setitimer(ovalue)", ARG3, sizeof(struct vki_itimerval));
2066}
2067
2068POST(sys_setitimer)
2069{
2070 if (ARG3 != (Addr)NULL) {
2071 POST_MEM_WRITE(ARG3, sizeof(struct vki_itimerval));
2072 }
2073}
2074
2075PRE(sys_chroot)
2076{
2077 PRINT("sys_chroot ( %p )", ARG1);
2078 PRE_REG_READ1(long, "chroot", const char *, path);
2079 PRE_MEM_RASCIIZ( "chroot(path)", ARG1 );
2080}
sewardja8d8e232005-06-07 20:04:56 +00002081
2082PRE(sys_madvise)
jsgf855d93d2003-10-13 22:26:55 +00002083{
sewardja8d8e232005-06-07 20:04:56 +00002084 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00002085 PRINT("sys_madvise ( %p, %llu, %d )", ARG1,(ULong)ARG2,ARG3);
nethercoteac866b92004-11-15 20:23:15 +00002086 PRE_REG_READ3(long, "madvise",
2087 unsigned long, start, vki_size_t, length, int, advice);
jsgf855d93d2003-10-13 22:26:55 +00002088}
2089
sewardja8d8e232005-06-07 20:04:56 +00002090PRE(sys_mremap)
jsgf855d93d2003-10-13 22:26:55 +00002091{
nethercote27ea8bc2004-07-10 17:21:14 +00002092 // Nb: this is different to the glibc version described in the man pages,
2093 // which lacks the fifth 'new_address' argument.
nethercote06c7bd72004-11-14 19:11:56 +00002094 PRINT("sys_mremap ( %p, %llu, %d, 0x%x, %p )",
njn22cfccb2004-11-27 16:10:23 +00002095 ARG1, (ULong)ARG2, ARG3, ARG4, ARG5);
nethercote06c7bd72004-11-14 19:11:56 +00002096 PRE_REG_READ5(unsigned long, "mremap",
2097 unsigned long, old_addr, unsigned long, old_size,
2098 unsigned long, new_size, unsigned long, flags,
2099 unsigned long, new_addr);
sewardja8d8e232005-06-07 20:04:56 +00002100 SET_STATUS_from_SysRes(
sewardj45f4e7c2005-09-27 19:20:21 +00002101 do_mremap((Addr)ARG1, ARG2, (Addr)ARG5, ARG3, ARG4, tid)
sewardja8d8e232005-06-07 20:04:56 +00002102 );
jsgf855d93d2003-10-13 22:26:55 +00002103}
2104
sewardj8c9ea4e2005-06-08 10:46:56 +00002105PRE(sys_nice)
2106{
2107 PRINT("sys_nice ( %d )", ARG1);
2108 PRE_REG_READ1(long, "nice", int, inc);
2109}
sewardj78b50e42005-06-08 01:47:28 +00002110
sewardj696c5512005-06-08 23:38:32 +00002111PRE(sys_mlock)
2112{
2113 *flags |= SfMayBlock;
2114 PRINT("sys_mlock ( %p, %llu )", ARG1, (ULong)ARG2);
2115 PRE_REG_READ2(long, "mlock", unsigned long, addr, vki_size_t, len);
2116}
2117
2118PRE(sys_munlock)
2119{
2120 *flags |= SfMayBlock;
2121 PRINT("sys_munlock ( %p, %llu )", ARG1, (ULong)ARG2);
2122 PRE_REG_READ2(long, "munlock", unsigned long, addr, vki_size_t, len);
2123}
2124
2125PRE(sys_mlockall)
2126{
2127 *flags |= SfMayBlock;
2128 PRINT("sys_mlockall ( %x )", ARG1);
2129 PRE_REG_READ1(long, "mlockall", int, flags);
2130}
2131
sewardj696c5512005-06-08 23:38:32 +00002132PRE(sys_setpriority)
2133{
2134 PRINT("sys_setpriority ( %d, %d, %d )", ARG1, ARG2, ARG3);
2135 PRE_REG_READ3(long, "setpriority", int, which, int, who, int, prio);
2136}
2137
2138PRE(sys_getpriority)
2139{
2140 PRINT("sys_getpriority ( %d, %d )", ARG1, ARG2);
2141 PRE_REG_READ2(long, "getpriority", int, which, int, who);
2142}
2143
tom4f08a652005-07-05 23:25:17 +00002144// The actual kernel definition of this routine takes a
2145// single 64 bit offset argument. This version is for 32 bit
2146// platforms only and treats the offset as two values - the
2147// kernel relies on stack based argument passing conventions
2148// to merge the two together.
sewardje6d5e722005-06-10 10:27:55 +00002149PRE(sys_pwrite64)
2150{
2151 *flags |= SfMayBlock;
2152 PRINT("sys_pwrite64 ( %d, %p, %llu, %lld )",
2153 ARG1, ARG2, (ULong)ARG3, LOHI64(ARG4,ARG5));
2154 PRE_REG_READ5(ssize_t, "pwrite64",
2155 unsigned int, fd, const char *, buf, vki_size_t, count,
2156 vki_u32, offset_low32, vki_u32, offset_high32);
2157 PRE_MEM_READ( "pwrite64(buf)", ARG2, ARG3 );
2158}
sewardj8c9ea4e2005-06-08 10:46:56 +00002159
2160PRE(sys_sync)
2161{
2162 *flags |= SfMayBlock;
2163 PRINT("sys_sync ( )");
2164 PRE_REG_READ0(long, "sync");
2165}
2166
sewardj696c5512005-06-08 23:38:32 +00002167PRE(sys_fstatfs)
2168{
2169 PRINT("sys_fstatfs ( %d, %p )",ARG1,ARG2);
2170 PRE_REG_READ2(long, "fstatfs",
2171 unsigned int, fd, struct statfs *, buf);
2172 PRE_MEM_WRITE( "fstatfs(buf)", ARG2, sizeof(struct vki_statfs) );
2173}
2174
2175POST(sys_fstatfs)
2176{
2177 POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs) );
2178}
2179
sewardje6d5e722005-06-10 10:27:55 +00002180PRE(sys_fstatfs64)
2181{
2182 PRINT("sys_fstatfs64 ( %d, %llu, %p )",ARG1,(ULong)ARG2,ARG3);
2183 PRE_REG_READ3(long, "fstatfs64",
2184 unsigned int, fd, vki_size_t, size, struct statfs64 *, buf);
2185 PRE_MEM_WRITE( "fstatfs64(buf)", ARG3, ARG2 );
2186}
2187POST(sys_fstatfs64)
2188{
2189 POST_MEM_WRITE( ARG3, ARG2 );
2190}
sewardj696c5512005-06-08 23:38:32 +00002191
2192PRE(sys_getsid)
2193{
2194 PRINT("sys_getsid ( %d )", ARG1);
2195 PRE_REG_READ1(long, "getsid", vki_pid_t, pid);
2196}
2197
tom4f08a652005-07-05 23:25:17 +00002198// The actual kernel definition of this routine takes a
2199// single 64 bit offset argument. This version is for 32 bit
2200// platforms only and treats the offset as two values - the
2201// kernel relies on stack based argument passing conventions
2202// to merge the two together.
sewardje7aa4ae2005-06-09 12:43:42 +00002203PRE(sys_pread64)
2204{
2205 *flags |= SfMayBlock;
2206 PRINT("sys_pread64 ( %d, %p, %llu, %lld )",
2207 ARG1, ARG2, (ULong)ARG3, LOHI64(ARG4,ARG5));
2208 PRE_REG_READ5(ssize_t, "pread64",
2209 unsigned int, fd, char *, buf, vki_size_t, count,
2210 vki_u32, offset_low32, vki_u32, offset_high32);
2211 PRE_MEM_WRITE( "pread64(buf)", ARG2, ARG3 );
2212}
2213POST(sys_pread64)
2214{
2215 vg_assert(SUCCESS);
2216 if (RES > 0) {
2217 POST_MEM_WRITE( ARG2, RES );
2218 }
2219}
jsgf855d93d2003-10-13 22:26:55 +00002220
sewardja8d8e232005-06-07 20:04:56 +00002221PRE(sys_mknod)
jsgf855d93d2003-10-13 22:26:55 +00002222{
njn22cfccb2004-11-27 16:10:23 +00002223 PRINT("sys_mknod ( %p, 0x%x, 0x%x )", ARG1, ARG2, ARG3 );
nethercotec6851dd2004-11-11 18:00:47 +00002224 PRE_REG_READ3(long, "mknod",
2225 const char *, pathname, int, mode, unsigned, dev);
njn22cfccb2004-11-27 16:10:23 +00002226 PRE_MEM_RASCIIZ( "mknod(pathname)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00002227}
2228
sewardj696c5512005-06-08 23:38:32 +00002229PRE(sys_flock)
2230{
2231 *flags |= SfMayBlock;
2232 PRINT("sys_flock ( %d, %d )", ARG1, ARG2 );
2233 PRE_REG_READ2(long, "flock", unsigned int, fd, unsigned int, operation);
2234}
2235
2236/* This surely isn't remotely generic -- move to linux-specifics? */
2237PRE(sys_init_module)
2238{
2239 *flags |= SfMayBlock;
2240 PRINT("sys_init_module ( %p, %llu, %p )", ARG1, (ULong)ARG2, ARG3 );
2241 PRE_REG_READ3(long, "init_module",
2242 void *, umod, unsigned long, len, const char *, uargs);
2243 PRE_MEM_READ( "init_module(umod)", ARG1, ARG2 );
2244 PRE_MEM_RASCIIZ( "init_module(uargs)", ARG3 );
2245}
2246
nethercotea81e9162004-02-12 14:34:14 +00002247// Pre_read a char** argument.
sewardjb5f6f512005-03-10 23:59:00 +00002248static void pre_argv_envp(Addr a, ThreadId tid, Char* s1, Char* s2)
nethercotea81e9162004-02-12 14:34:14 +00002249{
2250 while (True) {
njnb249fd72004-11-29 14:24:57 +00002251 Addr a_deref;
2252 Addr* a_p = (Addr*)a;
2253 PRE_MEM_READ( s1, (Addr)a_p, sizeof(Addr) );
2254 a_deref = *a_p;
nethercotea81e9162004-02-12 14:34:14 +00002255 if (0 == a_deref)
2256 break;
nethercoteef0c7662004-11-06 15:38:43 +00002257 PRE_MEM_RASCIIZ( s2, a_deref );
nethercotea81e9162004-02-12 14:34:14 +00002258 a += sizeof(char*);
2259 }
2260}
2261
njn7b85dd52005-06-12 17:26:29 +00002262static Bool i_am_the_only_thread ( void )
2263{
2264 Int c = VG_(count_living_threads)();
2265 vg_assert(c >= 1); /* stay sane */
2266 return c == 1;
2267}
2268
2269/* Wait until all other threads disappear. */
2270void VG_(reap_threads)(ThreadId self)
2271{
2272 while (!i_am_the_only_thread()) {
2273 /* Let other thread(s) run */
2274 VG_(vg_yield)();
2275 VG_(poll_signals)(self);
2276 }
2277 vg_assert(i_am_the_only_thread());
2278}
2279
nethercote7310afb2004-11-12 15:41:06 +00002280// XXX: prototype here seemingly doesn't match the prototype for i386-linux,
2281// but it seems to work nonetheless...
sewardja8d8e232005-06-07 20:04:56 +00002282PRE(sys_execve)
jsgf855d93d2003-10-13 22:26:55 +00002283{
sewardj45f4e7c2005-09-27 19:20:21 +00002284 Char* path = NULL; /* path to executable */
tom13696cc2005-07-18 23:23:03 +00002285 Char** envp = NULL;
sewardj45f4e7c2005-09-27 19:20:21 +00002286 Char** argv = NULL;
2287 Char** arg2copy;
2288 Char* launcher_basename = NULL;
sewardja8d8e232005-06-07 20:04:56 +00002289 ThreadState* tst;
sewardj45f4e7c2005-09-27 19:20:21 +00002290 Int i, j, tot_args;
njn73750612005-10-14 03:11:30 +00002291 SysRes res;
sewardjb5f6f512005-03-10 23:59:00 +00002292
njn22cfccb2004-11-27 16:10:23 +00002293 PRINT("sys_execve ( %p(%s), %p, %p )", ARG1, ARG1, ARG2, ARG3);
nethercote7310afb2004-11-12 15:41:06 +00002294 PRE_REG_READ3(vki_off_t, "execve",
2295 char *, filename, char **, argv, char **, envp);
njn22cfccb2004-11-27 16:10:23 +00002296 PRE_MEM_RASCIIZ( "execve(filename)", ARG1 );
2297 if (ARG2 != 0)
2298 pre_argv_envp( ARG2, tid, "execve(argv)", "execve(argv[i])" );
2299 if (ARG3 != 0)
2300 pre_argv_envp( ARG3, tid, "execve(envp)", "execve(envp[i])" );
fitzhardingee1c06d82003-10-30 07:21:44 +00002301
sewardja8d8e232005-06-07 20:04:56 +00002302 vg_assert(VG_(is_valid_tid)(tid));
2303 tst = VG_(get_ThreadState)(tid);
2304
fitzhardingee1c06d82003-10-30 07:21:44 +00002305 /* Erk. If the exec fails, then the following will have made a
2306 mess of things which makes it hard for us to continue. The
2307 right thing to do is piece everything together again in
sewardj45f4e7c2005-09-27 19:20:21 +00002308 POST(execve), but that's close to impossible. Instead, we make
2309 an effort to check that the execve will work before actually
2310 doing it. */
fitzhardingee1c06d82003-10-30 07:21:44 +00002311
njn73750612005-10-14 03:11:30 +00002312 /* Check that the name at least begins in client-accessible storage. */
sewardj45f4e7c2005-09-27 19:20:21 +00002313 if (!VG_(am_is_valid_for_client)( ARG1, 1, VKI_PROT_READ )) {
2314 SET_STATUS_Failure( VKI_EFAULT );
2315 return;
2316 }
2317
njn73750612005-10-14 03:11:30 +00002318 // Do the important checks: it is a file, is executable, permissions are
2319 // ok, etc.
2320 res = VG_(pre_exec_check)((const Char*)ARG1, NULL);
2321 if (res.isError) {
2322 SET_STATUS_Failure( res.val );
2323 return;
2324 }
2325
sewardj98e68a42005-10-04 23:07:33 +00002326 /* If we're tracing the child, and the launcher name looks bogus
2327 (possibly because launcher.c couldn't figure it out, see
2328 comments therein) then we have no option but to fail. */
2329 if (VG_(clo_trace_children)
2330 && (VG_(name_of_launcher) == NULL
2331 || VG_(name_of_launcher)[0] != '/')) {
2332 SET_STATUS_Failure( VKI_ECHILD ); /* "No child processes" */
2333 return;
2334 }
2335
sewardj45f4e7c2005-09-27 19:20:21 +00002336 /* After this point, we can't recover if the execve fails. */
2337 VG_(debugLog)(1, "syswrap", "Exec of %s\n", (Char*)ARG1);
2338
fitzhardingee1c06d82003-10-30 07:21:44 +00002339 /* Resistance is futile. Nuke all other threads. POSIX mandates
2340 this. (Really, nuke them all, since the new process will make
2341 its own new thread.) */
sewardjb5f6f512005-03-10 23:59:00 +00002342 VG_(nuke_all_threads_except)( tid, VgSrc_ExitSyscall );
njn7b85dd52005-06-12 17:26:29 +00002343 VG_(reap_threads)(tid);
sewardjb5f6f512005-03-10 23:59:00 +00002344
sewardj45f4e7c2005-09-27 19:20:21 +00002345 // Set up the child's exe path.
2346 //
2347 if (VG_(clo_trace_children)) {
2348
2349 // We want to exec the launcher. Get its pre-remembered path.
2350 path = VG_(name_of_launcher);
2351 // VG_(name_of_launcher) should have been acquired by m_main at
2352 // startup.
2353 vg_assert(path);
2354
2355 launcher_basename = VG_(strrchr)(path, '/');
2356 if (launcher_basename == NULL || launcher_basename[1] == 0) {
2357 launcher_basename = path; // hmm, tres dubious
2358 } else {
2359 launcher_basename++;
2360 }
2361
2362 } else {
2363 path = (Char*)ARG1;
2364 }
2365
2366 // Set up the child's environment.
2367 //
tom4e136952005-07-18 14:02:11 +00002368 // Remove the valgrind-specific stuff from the environment so the
njn7b4e5ba2005-08-25 22:53:57 +00002369 // child doesn't get vgpreload_core.so, vgpreload_<tool>.so, etc.
tom4e136952005-07-18 14:02:11 +00002370 // This is done unconditionally, since if we are tracing the child,
sewardj45f4e7c2005-09-27 19:20:21 +00002371 // the child valgrind will set up the appropriate client environment.
njn11106992005-07-18 14:10:12 +00002372 // Nb: we make a copy of the environment before trying to mangle it
2373 // as it might be in read-only memory (this was bug #101881).
sewardj45f4e7c2005-09-27 19:20:21 +00002374 //
2375 // Then, if tracing the child, set VALGRIND_LIB for it.
2376 //
2377 if (ARG3 == 0) {
2378 envp = NULL;
2379 } else {
tom13696cc2005-07-18 23:23:03 +00002380 envp = VG_(env_clone)( (Char**)ARG3 );
sewardj45f4e7c2005-09-27 19:20:21 +00002381 if (envp == NULL) goto hosed;
tom4e136952005-07-18 14:02:11 +00002382 VG_(env_remove_valgrind_env_stuff)( envp );
fitzhardinge5408c062004-01-04 23:52:59 +00002383 }
2384
2385 if (VG_(clo_trace_children)) {
sewardj45f4e7c2005-09-27 19:20:21 +00002386 // Set VALGRIND_LIB in ARG3 (the environment)
2387 VG_(env_setenv)( &envp, VALGRIND_LIB, VG_(libdir));
fitzhardinge98abfc72003-12-16 02:05:15 +00002388 }
2389
sewardj45f4e7c2005-09-27 19:20:21 +00002390 // Set up the child's args. If not tracing it, they are
2391 // simply ARG2. Otherwise, they are
2392 //
2393 // [launcher_basename] ++ VG_(args_for_valgrind) ++ [ARG1] ++ ARG2[1..]
2394 //
2395 // except that the first VG_(args_for_valgrind_noexecpass) args
2396 // are omitted.
2397 //
2398 if (!VG_(clo_trace_children)) {
2399 argv = (Char**)ARG2;
2400 } else {
2401 vg_assert( VG_(args_for_valgrind_noexecpass) >= 0 );
2402 vg_assert( VG_(args_for_valgrind_noexecpass)
2403 <= VG_(args_for_valgrind).used );
2404 /* how many args in total will there be? */
2405 // launcher basename
2406 tot_args = 1;
2407 // V's args
2408 tot_args += VG_(args_for_valgrind).used;
2409 tot_args -= VG_(args_for_valgrind_noexecpass);
2410 // name of client exe
2411 tot_args++;
2412 // args for client exe, skipping [0]
2413 arg2copy = (Char**)ARG2;
2414 if (arg2copy && arg2copy[0]) {
2415 for (i = 1; arg2copy[i]; i++)
2416 tot_args++;
2417 }
2418 // allocate
2419 argv = VG_(malloc)( (tot_args+1) * sizeof(HChar*) );
2420 if (argv == 0) goto hosed;
2421 // copy
2422 j = 0;
2423 argv[j++] = launcher_basename;
2424 for (i = 0; i < VG_(args_for_valgrind).used; i++) {
2425 if (i < VG_(args_for_valgrind_noexecpass))
2426 continue;
2427 argv[j++] = VG_(args_for_valgrind).strs[i];
2428 }
2429 argv[j++] = (Char*)ARG1;
2430 if (arg2copy && arg2copy[0])
2431 for (i = 1; arg2copy[i]; i++)
2432 argv[j++] = arg2copy[i];
2433 argv[j++] = NULL;
2434 // check
2435 vg_assert(j == tot_args+1);
jsgf855d93d2003-10-13 22:26:55 +00002436 }
jsgf855d93d2003-10-13 22:26:55 +00002437
sewardjb5f6f512005-03-10 23:59:00 +00002438 /* restore the DATA rlimit for the child */
2439 VG_(setrlimit)(VKI_RLIMIT_DATA, &VG_(client_rlimit_data));
2440
2441 /*
2442 Set the signal state up for exec.
2443
2444 We need to set the real signal state to make sure the exec'd
2445 process gets SIG_IGN properly.
2446
2447 Also set our real sigmask to match the client's sigmask so that
2448 the exec'd child will get the right mask. First we need to
2449 clear out any pending signals so they they don't get delivered,
2450 which would confuse things.
fitzhardingef0dd7e12004-01-16 02:17:30 +00002451
2452 XXX This is a bug - the signals should remain pending, and be
2453 delivered to the new process after exec. There's also a
2454 race-condition, since if someone delivers us a signal between
2455 the sigprocmask and the execve, we'll still get the signal. Oh
2456 well.
2457 */
2458 {
nethercote73b526f2004-10-31 18:48:21 +00002459 vki_sigset_t allsigs;
2460 vki_siginfo_t info;
fitzhardingef0dd7e12004-01-16 02:17:30 +00002461 static const struct vki_timespec zero = { 0, 0 };
sewardjb5f6f512005-03-10 23:59:00 +00002462
sewardj45f4e7c2005-09-27 19:20:21 +00002463 for (i = 1; i < VG_(max_signal); i++) {
sewardjb5f6f512005-03-10 23:59:00 +00002464 struct vki_sigaction sa;
2465 VG_(do_sys_sigaction)(i, NULL, &sa);
2466 if (sa.ksa_handler == VKI_SIG_IGN)
2467 VG_(sigaction)(i, &sa, NULL);
2468 else {
2469 sa.ksa_handler = VKI_SIG_DFL;
2470 VG_(sigaction)(i, &sa, NULL);
2471 }
2472 }
2473
nethercote73b526f2004-10-31 18:48:21 +00002474 VG_(sigfillset)(&allsigs);
2475 while(VG_(sigtimedwait)(&allsigs, &info, &zero) > 0)
sewardjb5f6f512005-03-10 23:59:00 +00002476 ;
fitzhardingef0dd7e12004-01-16 02:17:30 +00002477
nethercote73b526f2004-10-31 18:48:21 +00002478 VG_(sigprocmask)(VKI_SIG_SETMASK, &tst->sig_mask, NULL);
fitzhardingef0dd7e12004-01-16 02:17:30 +00002479 }
2480
sewardj45f4e7c2005-09-27 19:20:21 +00002481 if (0) {
2482 Char **cpp;
2483 VG_(printf)("exec: %s\n", path);
2484 for (cpp = argv; cpp && *cpp; cpp++)
2485 VG_(printf)("argv: %s\n", *cpp);
2486 if (0)
2487 for (cpp = envp; cpp && *cpp; cpp++)
2488 VG_(printf)("env: %s\n", *cpp);
2489 }
2490
sewardja8d8e232005-06-07 20:04:56 +00002491 SET_STATUS_from_SysRes(
sewardj45f4e7c2005-09-27 19:20:21 +00002492 VG_(do_syscall3)(__NR_execve, (UWord)path, (UWord)argv, (UWord)envp)
sewardja8d8e232005-06-07 20:04:56 +00002493 );
fitzhardingeb50068f2004-02-24 23:42:55 +00002494
sewardj45f4e7c2005-09-27 19:20:21 +00002495 /* If we got here, then the execve failed. We've already made way
2496 too much of a mess to continue, so we have to abort. */
2497 hosed:
tomdc294c32005-08-16 10:19:58 +00002498 vg_assert(FAILURE);
nethercotee70bd7d2004-08-18 14:37:17 +00002499 VG_(message)(Vg_UserMsg, "execve(%p(%s), %p, %p) failed, errno %d",
tomdc294c32005-08-16 10:19:58 +00002500 ARG1, ARG1, ARG2, ARG3, RES_unchecked);
sewardjb5f6f512005-03-10 23:59:00 +00002501 VG_(message)(Vg_UserMsg, "EXEC FAILED: I can't recover from "
2502 "execve() failing, so I'm dying.");
sewardja8d8e232005-06-07 20:04:56 +00002503 VG_(message)(Vg_UserMsg, "Add more stringent tests in PRE(sys_execve), "
sewardjb5f6f512005-03-10 23:59:00 +00002504 "or work out how to recover.");
2505 VG_(exit)(101);
jsgf855d93d2003-10-13 22:26:55 +00002506}
2507
sewardja8d8e232005-06-07 20:04:56 +00002508PRE(sys_access)
jsgf855d93d2003-10-13 22:26:55 +00002509{
njn22cfccb2004-11-27 16:10:23 +00002510 PRINT("sys_access ( %p(%s), %d )", ARG1,ARG1,ARG2);
nethercote9a3beb92004-11-12 17:07:26 +00002511 PRE_REG_READ2(long, "access", const char *, pathname, int, mode);
njn22cfccb2004-11-27 16:10:23 +00002512 PRE_MEM_RASCIIZ( "access(pathname)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00002513}
2514
sewardja8d8e232005-06-07 20:04:56 +00002515PRE(sys_alarm)
jsgf855d93d2003-10-13 22:26:55 +00002516{
njn22cfccb2004-11-27 16:10:23 +00002517 PRINT("sys_alarm ( %d )", ARG1);
nethercote9a3beb92004-11-12 17:07:26 +00002518 PRE_REG_READ1(unsigned long, "alarm", unsigned int, seconds);
jsgf855d93d2003-10-13 22:26:55 +00002519}
2520
sewardja8d8e232005-06-07 20:04:56 +00002521PRE(sys_brk)
jsgf855d93d2003-10-13 22:26:55 +00002522{
fitzhardinge98abfc72003-12-16 02:05:15 +00002523 Addr brk_limit = VG_(brk_limit);
sewardja8d8e232005-06-07 20:04:56 +00002524 Addr brk_new;
fitzhardinge98abfc72003-12-16 02:05:15 +00002525
jsgf855d93d2003-10-13 22:26:55 +00002526 /* libc says: int brk(void *end_data_segment);
2527 kernel says: void* brk(void* end_data_segment); (more or less)
2528
2529 libc returns 0 on success, and -1 (and sets errno) on failure.
2530 Nb: if you ask to shrink the dataseg end below what it
2531 currently is, that always succeeds, even if the dataseg end
2532 doesn't actually change (eg. brk(0)). Unless it seg faults.
2533
2534 Kernel returns the new dataseg end. If the brk() failed, this
2535 will be unchanged from the old one. That's why calling (kernel)
2536 brk(0) gives the current dataseg end (libc brk() just returns
2537 zero in that case).
2538
2539 Both will seg fault if you shrink it back into a text segment.
2540 */
njn22cfccb2004-11-27 16:10:23 +00002541 PRINT("sys_brk ( %p )", ARG1);
nethercote9c311eb2004-11-12 18:20:12 +00002542 PRE_REG_READ1(unsigned long, "brk", unsigned long, end_data_segment);
jsgf855d93d2003-10-13 22:26:55 +00002543
sewardja8d8e232005-06-07 20:04:56 +00002544 brk_new = do_brk(ARG1);
2545 SET_STATUS_Success( brk_new );
fitzhardinge98abfc72003-12-16 02:05:15 +00002546
sewardja8d8e232005-06-07 20:04:56 +00002547 if (brk_new == ARG1) {
jsgf855d93d2003-10-13 22:26:55 +00002548 /* brk() succeeded */
sewardja8d8e232005-06-07 20:04:56 +00002549 if (brk_new < brk_limit) {
jsgf855d93d2003-10-13 22:26:55 +00002550 /* successfully shrunk the data segment. */
njn22cfccb2004-11-27 16:10:23 +00002551 VG_TRACK( die_mem_brk, (Addr)ARG1,
2552 brk_limit-ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00002553 } else
sewardja8d8e232005-06-07 20:04:56 +00002554 if (brk_new > brk_limit) {
jsgf855d93d2003-10-13 22:26:55 +00002555 /* successfully grew the data segment */
fitzhardinge98abfc72003-12-16 02:05:15 +00002556 VG_TRACK( new_mem_brk, brk_limit,
njn22cfccb2004-11-27 16:10:23 +00002557 ARG1-brk_limit );
jsgf855d93d2003-10-13 22:26:55 +00002558 }
jsgf855d93d2003-10-13 22:26:55 +00002559 } else {
2560 /* brk() failed */
sewardja8d8e232005-06-07 20:04:56 +00002561 vg_assert(brk_limit == brk_new);
jsgf855d93d2003-10-13 22:26:55 +00002562 }
2563}
2564
sewardja8d8e232005-06-07 20:04:56 +00002565PRE(sys_chdir)
jsgf855d93d2003-10-13 22:26:55 +00002566{
njn22cfccb2004-11-27 16:10:23 +00002567 PRINT("sys_chdir ( %p )", ARG1);
nethercotec6851dd2004-11-11 18:00:47 +00002568 PRE_REG_READ1(long, "chdir", const char *, path);
njn22cfccb2004-11-27 16:10:23 +00002569 PRE_MEM_RASCIIZ( "chdir(path)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00002570}
2571
sewardja8d8e232005-06-07 20:04:56 +00002572PRE(sys_chmod)
jsgf855d93d2003-10-13 22:26:55 +00002573{
njn22cfccb2004-11-27 16:10:23 +00002574 PRINT("sys_chmod ( %p, %d )", ARG1,ARG2);
nethercotec6851dd2004-11-11 18:00:47 +00002575 PRE_REG_READ2(long, "chmod", const char *, path, vki_mode_t, mode);
njn22cfccb2004-11-27 16:10:23 +00002576 PRE_MEM_RASCIIZ( "chmod(path)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00002577}
2578
sewardje6d5e722005-06-10 10:27:55 +00002579PRE(sys_chown)
2580{
sewardje6d5e722005-06-10 10:27:55 +00002581 PRINT("sys_chown ( %p, 0x%x, 0x%x )", ARG1,ARG2,ARG3);
2582 PRE_REG_READ3(long, "chown",
2583 const char *, path, vki_uid_t, owner, vki_gid_t, group);
2584 PRE_MEM_RASCIIZ( "chown(path)", ARG1 );
2585}
2586
2587PRE(sys_lchown)
2588{
2589 PRINT("sys_lchown ( %p, 0x%x, 0x%x )", ARG1,ARG2,ARG3);
2590 PRE_REG_READ3(long, "lchown",
2591 const char *, path, vki_uid_t, owner, vki_gid_t, group);
2592 PRE_MEM_RASCIIZ( "lchown(path)", ARG1 );
2593}
nethercote2e1c37d2004-11-13 13:57:12 +00002594
sewardja8d8e232005-06-07 20:04:56 +00002595PRE(sys_close)
jsgf855d93d2003-10-13 22:26:55 +00002596{
njn22cfccb2004-11-27 16:10:23 +00002597 PRINT("sys_close ( %d )", ARG1);
nethercotec6851dd2004-11-11 18:00:47 +00002598 PRE_REG_READ1(long, "close", unsigned int, fd);
2599
nethercotef8548672004-06-21 12:42:35 +00002600 /* Detect and negate attempts by the client to close Valgrind's log fd */
sewardj7eb7c582005-06-23 01:02:53 +00002601 if (!ML_(fd_allowed)(ARG1, "close", tid, False))
sewardja8d8e232005-06-07 20:04:56 +00002602 SET_STATUS_Failure( VKI_EBADF );
jsgf855d93d2003-10-13 22:26:55 +00002603}
2604
nethercote85a456f2004-11-16 17:31:56 +00002605POST(sys_close)
rjwalshf5f536f2003-11-17 17:45:00 +00002606{
njn22cfccb2004-11-27 16:10:23 +00002607 if (VG_(clo_track_fds)) record_fd_close(tid, ARG1);
rjwalshf5f536f2003-11-17 17:45:00 +00002608}
jsgf855d93d2003-10-13 22:26:55 +00002609
sewardja8d8e232005-06-07 20:04:56 +00002610PRE(sys_dup)
jsgf855d93d2003-10-13 22:26:55 +00002611{
njn22cfccb2004-11-27 16:10:23 +00002612 PRINT("sys_dup ( %d )", ARG1);
nethercote9a3beb92004-11-12 17:07:26 +00002613 PRE_REG_READ1(long, "dup", unsigned int, oldfd);
jsgf855d93d2003-10-13 22:26:55 +00002614}
2615
nethercote85a456f2004-11-16 17:31:56 +00002616POST(sys_dup)
jsgf855d93d2003-10-13 22:26:55 +00002617{
sewardja8d8e232005-06-07 20:04:56 +00002618 vg_assert(SUCCESS);
sewardj7eb7c582005-06-23 01:02:53 +00002619 if (!ML_(fd_allowed)(RES, "dup", tid, True)) {
njn22cfccb2004-11-27 16:10:23 +00002620 VG_(close)(RES);
sewardja8d8e232005-06-07 20:04:56 +00002621 SET_STATUS_Failure( VKI_EMFILE );
rjwalshf5f536f2003-11-17 17:45:00 +00002622 } else {
nethercote9a3beb92004-11-12 17:07:26 +00002623 if (VG_(clo_track_fds))
njnf845f8f2005-06-23 02:26:47 +00002624 record_fd_open_named(tid, RES);
jsgf855d93d2003-10-13 22:26:55 +00002625 }
2626}
2627
sewardja8d8e232005-06-07 20:04:56 +00002628PRE(sys_dup2)
jsgf855d93d2003-10-13 22:26:55 +00002629{
njn22cfccb2004-11-27 16:10:23 +00002630 PRINT("sys_dup2 ( %d, %d )", ARG1,ARG2);
nethercote71f05f32004-11-12 18:49:27 +00002631 PRE_REG_READ2(long, "dup2", unsigned int, oldfd, unsigned int, newfd);
sewardj7eb7c582005-06-23 01:02:53 +00002632 if (!ML_(fd_allowed)(ARG2, "dup2", tid, True))
sewardja8d8e232005-06-07 20:04:56 +00002633 SET_STATUS_Failure( VKI_EBADF );
jsgf855d93d2003-10-13 22:26:55 +00002634}
2635
nethercote85a456f2004-11-16 17:31:56 +00002636POST(sys_dup2)
jsgf855d93d2003-10-13 22:26:55 +00002637{
sewardja8d8e232005-06-07 20:04:56 +00002638 vg_assert(SUCCESS);
nethercote71f05f32004-11-12 18:49:27 +00002639 if (VG_(clo_track_fds))
njnf845f8f2005-06-23 02:26:47 +00002640 record_fd_open_named(tid, RES);
jsgf855d93d2003-10-13 22:26:55 +00002641}
2642
sewardj696c5512005-06-08 23:38:32 +00002643PRE(sys_fchdir)
2644{
2645 PRINT("sys_fchdir ( %d )", ARG1);
2646 PRE_REG_READ1(long, "fchdir", unsigned int, fd);
2647}
2648
sewardje6d5e722005-06-10 10:27:55 +00002649PRE(sys_fchown)
2650{
2651 PRINT("sys_fchown ( %d, %d, %d )", ARG1,ARG2,ARG3);
2652 PRE_REG_READ3(long, "fchown",
2653 unsigned int, fd, vki_uid_t, owner, vki_gid_t, group);
2654}
sewardj696c5512005-06-08 23:38:32 +00002655
2656PRE(sys_fchmod)
2657{
2658 PRINT("sys_fchmod ( %d, %d )", ARG1,ARG2);
2659 PRE_REG_READ2(long, "fchmod", unsigned int, fildes, vki_mode_t, mode);
2660}
2661
2662PRE(sys_fcntl)
2663{
2664 switch (ARG2) {
2665 // These ones ignore ARG3.
2666 case VKI_F_GETFD:
2667 case VKI_F_GETFL:
2668 case VKI_F_GETOWN:
sewardj696c5512005-06-08 23:38:32 +00002669 case VKI_F_GETSIG:
sewardj696c5512005-06-08 23:38:32 +00002670 case VKI_F_GETLEASE:
2671 PRINT("sys_fcntl ( %d, %d )", ARG1,ARG2);
2672 PRE_REG_READ2(long, "fcntl", unsigned int, fd, unsigned int, cmd);
2673 break;
2674
2675 // These ones use ARG3 as "arg".
2676 case VKI_F_DUPFD:
2677 case VKI_F_SETFD:
2678 case VKI_F_SETFL:
2679 case VKI_F_SETLEASE:
2680 case VKI_F_NOTIFY:
njn4ae40402005-08-24 13:55:59 +00002681 case VKI_F_SETOWN:
2682 case VKI_F_SETSIG:
sewardj696c5512005-06-08 23:38:32 +00002683 PRINT("sys_fcntl[ARG3=='arg'] ( %d, %d, %d )", ARG1,ARG2,ARG3);
2684 PRE_REG_READ3(long, "fcntl",
2685 unsigned int, fd, unsigned int, cmd, unsigned long, arg);
2686 break;
2687
2688 // These ones use ARG3 as "lock".
2689 case VKI_F_GETLK:
2690 case VKI_F_SETLK:
2691 case VKI_F_SETLKW:
sewardje7aa4ae2005-06-09 12:43:42 +00002692# if defined(VGP_x86_linux)
sewardj696c5512005-06-08 23:38:32 +00002693 case VKI_F_GETLK64:
2694 case VKI_F_SETLK64:
2695 case VKI_F_SETLKW64:
2696# else
2697# endif
2698 PRINT("sys_fcntl[ARG3=='lock'] ( %d, %d, %p )", ARG1,ARG2,ARG3);
2699 PRE_REG_READ3(long, "fcntl",
2700 unsigned int, fd, unsigned int, cmd,
2701 struct flock64 *, lock);
2702 break;
2703 }
2704
2705 if (ARG2 == VKI_F_SETLKW)
2706 *flags |= SfMayBlock;
2707}
2708
2709POST(sys_fcntl)
2710{
2711 vg_assert(SUCCESS);
2712 if (ARG2 == VKI_F_DUPFD) {
sewardj7eb7c582005-06-23 01:02:53 +00002713 if (!ML_(fd_allowed)(RES, "fcntl(DUPFD)", tid, True)) {
sewardj696c5512005-06-08 23:38:32 +00002714 VG_(close)(RES);
2715 SET_STATUS_Failure( VKI_EMFILE );
2716 } else {
2717 if (VG_(clo_track_fds))
njnf845f8f2005-06-23 02:26:47 +00002718 record_fd_open_named(tid, RES);
sewardj696c5512005-06-08 23:38:32 +00002719 }
2720 }
2721}
njncfb8ad52004-11-23 14:57:49 +00002722
nethercote06c7bd72004-11-14 19:11:56 +00002723// XXX: wrapper only suitable for 32-bit systems
sewardja8d8e232005-06-07 20:04:56 +00002724PRE(sys_fcntl64)
jsgf855d93d2003-10-13 22:26:55 +00002725{
njnc6168192004-11-29 13:54:10 +00002726 switch (ARG2) {
2727 // These ones ignore ARG3.
2728 case VKI_F_GETFD:
2729 case VKI_F_GETFL:
2730 case VKI_F_GETOWN:
2731 case VKI_F_SETOWN:
2732 case VKI_F_GETSIG:
2733 case VKI_F_SETSIG:
2734 case VKI_F_GETLEASE:
2735 PRINT("sys_fcntl64 ( %d, %d )", ARG1,ARG2);
2736 PRE_REG_READ2(long, "fcntl64", unsigned int, fd, unsigned int, cmd);
2737 break;
2738
2739 // These ones use ARG3 as "arg".
2740 case VKI_F_DUPFD:
2741 case VKI_F_SETFD:
2742 case VKI_F_SETFL:
2743 case VKI_F_SETLEASE:
2744 case VKI_F_NOTIFY:
2745 PRINT("sys_fcntl64[ARG3=='arg'] ( %d, %d, %d )", ARG1,ARG2,ARG3);
2746 PRE_REG_READ3(long, "fcntl64",
2747 unsigned int, fd, unsigned int, cmd, unsigned long, arg);
2748 break;
2749
2750 // These ones use ARG3 as "lock".
2751 case VKI_F_GETLK:
2752 case VKI_F_SETLK:
2753 case VKI_F_SETLKW:
sewardje7aa4ae2005-06-09 12:43:42 +00002754# if defined(VGP_x86_linux)
njnc6168192004-11-29 13:54:10 +00002755 case VKI_F_GETLK64:
2756 case VKI_F_SETLK64:
2757 case VKI_F_SETLKW64:
sewardja8d8e232005-06-07 20:04:56 +00002758# endif
njnc6168192004-11-29 13:54:10 +00002759 PRINT("sys_fcntl64[ARG3=='lock'] ( %d, %d, %p )", ARG1,ARG2,ARG3);
2760 PRE_REG_READ3(long, "fcntl64",
2761 unsigned int, fd, unsigned int, cmd,
2762 struct flock64 *, lock);
2763 break;
2764 }
njncfb8ad52004-11-23 14:57:49 +00002765
sewardje7aa4ae2005-06-09 12:43:42 +00002766# if defined(VGP_x86_linux)
2767 if (ARG2 == VKI_F_SETLKW || ARG2 == VKI_F_SETLKW64)
2768 *flags |= SfMayBlock;
sewardja8d8e232005-06-07 20:04:56 +00002769# else
sewardje7aa4ae2005-06-09 12:43:42 +00002770 if (ARG2 == VKI_F_SETLKW)
2771 *flags |= SfMayBlock;
sewardja8d8e232005-06-07 20:04:56 +00002772# endif
rjwalshf5f536f2003-11-17 17:45:00 +00002773}
2774
nethercote85a456f2004-11-16 17:31:56 +00002775POST(sys_fcntl64)
rjwalshf5f536f2003-11-17 17:45:00 +00002776{
sewardja8d8e232005-06-07 20:04:56 +00002777 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00002778 if (ARG2 == VKI_F_DUPFD) {
sewardj7eb7c582005-06-23 01:02:53 +00002779 if (!ML_(fd_allowed)(RES, "fcntl64(DUPFD)", tid, True)) {
njn22cfccb2004-11-27 16:10:23 +00002780 VG_(close)(RES);
sewardja8d8e232005-06-07 20:04:56 +00002781 SET_STATUS_Failure( VKI_EMFILE );
nethercote493dd182004-02-24 23:57:47 +00002782 } else {
2783 if (VG_(clo_track_fds))
njnf845f8f2005-06-23 02:26:47 +00002784 record_fd_open_named(tid, RES);
nethercote493dd182004-02-24 23:57:47 +00002785 }
2786 }
jsgf855d93d2003-10-13 22:26:55 +00002787}
2788
sewardj696c5512005-06-08 23:38:32 +00002789PRE(sys_newfstat)
2790{
2791 PRINT("sys_newfstat ( %d, %p )", ARG1,ARG2);
2792 PRE_REG_READ2(long, "fstat", unsigned int, fd, struct stat *, buf);
2793 PRE_MEM_WRITE( "fstat(buf)", ARG2, sizeof(struct vki_stat) );
2794}
2795
2796POST(sys_newfstat)
2797{
2798 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
2799}
jsgf855d93d2003-10-13 22:26:55 +00002800
nethercote73b526f2004-10-31 18:48:21 +00002801static vki_sigset_t fork_saved_mask;
jsgf855d93d2003-10-13 22:26:55 +00002802
nethercote75a8c982004-11-11 19:03:34 +00002803// In Linux, the sys_fork() function varies across architectures, but we
2804// ignore the various args it gets, and so it looks arch-neutral. Hmm.
sewardja8d8e232005-06-07 20:04:56 +00002805PRE(sys_fork)
jsgf855d93d2003-10-13 22:26:55 +00002806{
nethercote73b526f2004-10-31 18:48:21 +00002807 vki_sigset_t mask;
jsgf855d93d2003-10-13 22:26:55 +00002808
nethercote75a8c982004-11-11 19:03:34 +00002809 PRINT("sys_fork ( )");
2810 PRE_REG_READ0(long, "fork");
2811
jsgf855d93d2003-10-13 22:26:55 +00002812 /* Block all signals during fork, so that we can fix things up in
2813 the child without being interrupted. */
nethercote73b526f2004-10-31 18:48:21 +00002814 VG_(sigfillset)(&mask);
2815 VG_(sigprocmask)(VKI_SIG_SETMASK, &mask, &fork_saved_mask);
jsgf855d93d2003-10-13 22:26:55 +00002816
sewardja8d8e232005-06-07 20:04:56 +00002817 SET_STATUS_from_SysRes( VG_(do_syscall0)(__NR_fork) );
sewardjb5f6f512005-03-10 23:59:00 +00002818
sewardja8d8e232005-06-07 20:04:56 +00002819 if (SUCCESS && RES == 0) {
sewardjb5f6f512005-03-10 23:59:00 +00002820 VG_(do_atfork_child)(tid);
jsgf855d93d2003-10-13 22:26:55 +00002821
2822 /* restore signal mask */
nethercote73b526f2004-10-31 18:48:21 +00002823 VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
sewardja8d8e232005-06-07 20:04:56 +00002824 }
2825 else
2826 if (SUCCESS && RES > 0) {
sewardjb5f6f512005-03-10 23:59:00 +00002827 PRINT(" fork: process %d created child %d\n", VG_(getpid)(), RES);
jsgf855d93d2003-10-13 22:26:55 +00002828
jsgf855d93d2003-10-13 22:26:55 +00002829 /* restore signal mask */
nethercote73b526f2004-10-31 18:48:21 +00002830 VG_(sigprocmask)(VKI_SIG_SETMASK, &fork_saved_mask, NULL);
jsgf855d93d2003-10-13 22:26:55 +00002831 }
2832}
2833
sewardj8c257322005-06-08 01:01:48 +00002834PRE(sys_ftruncate)
2835{
2836 *flags |= SfMayBlock;
njn68e46592005-08-26 19:42:27 +00002837 PRINT("sys_ftruncate ( %d, %ld )", ARG1,ARG2);
sewardj8c257322005-06-08 01:01:48 +00002838 PRE_REG_READ2(long, "ftruncate", unsigned int, fd, unsigned long, length);
2839}
2840
sewardj696c5512005-06-08 23:38:32 +00002841PRE(sys_truncate)
2842{
2843 *flags |= SfMayBlock;
2844 PRINT("sys_truncate ( %p(%s), %d )", ARG1,ARG1,ARG2);
2845 PRE_REG_READ2(long, "truncate",
2846 const char *, path, unsigned long, length);
2847 PRE_MEM_RASCIIZ( "truncate(path)", ARG1 );
2848}
2849
sewardje6d5e722005-06-10 10:27:55 +00002850// XXX: this wrapper is only suitable for 32-bit platforms
sewardj48db0f02005-10-07 13:30:48 +00002851#if defined(VGP_x86_linux) || defined(VGP_ppc32_linux)
sewardje6d5e722005-06-10 10:27:55 +00002852PRE(sys_ftruncate64)
2853{
2854 *flags |= SfMayBlock;
2855 PRINT("sys_ftruncate64 ( %d, %lld )", ARG1, LOHI64(ARG2,ARG3));
2856 PRE_REG_READ3(long, "ftruncate64",
2857 unsigned int, fd,
2858 vki_u32, length_low32, vki_u32, length_high32);
2859}
2860#endif
2861
2862// XXX: this wrapper is only suitable for 32-bit platforms
2863#if defined(VGP_x86_linux)
2864PRE(sys_truncate64)
2865{
2866 *flags |= SfMayBlock;
2867 PRINT("sys_truncate64 ( %p, %lld )", ARG1, LOHI64(ARG2, ARG3));
2868 PRE_REG_READ3(long, "truncate64",
2869 const char *, path,
2870 vki_u32, length_low32, vki_u32, length_high32);
2871 PRE_MEM_RASCIIZ( "truncate64(path)", ARG1 );
2872}
2873#endif
sewardj78b50e42005-06-08 01:47:28 +00002874
2875PRE(sys_getdents)
2876{
2877 *flags |= SfMayBlock;
2878 PRINT("sys_getdents ( %d, %p, %d )", ARG1,ARG2,ARG3);
2879 PRE_REG_READ3(long, "getdents",
2880 unsigned int, fd, struct linux_dirent *, dirp,
2881 unsigned int, count);
2882 PRE_MEM_WRITE( "getdents(dirp)", ARG2, ARG3 );
2883}
2884
2885POST(sys_getdents)
2886{
2887 vg_assert(SUCCESS);
2888 if (RES > 0)
2889 POST_MEM_WRITE( ARG2, RES );
2890}
jsgf855d93d2003-10-13 22:26:55 +00002891
sewardja8d8e232005-06-07 20:04:56 +00002892PRE(sys_getdents64)
jsgf855d93d2003-10-13 22:26:55 +00002893{
sewardj78b50e42005-06-08 01:47:28 +00002894 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00002895 PRINT("sys_getdents64 ( %d, %p, %d )",ARG1,ARG2,ARG3);
nethercote06c7bd72004-11-14 19:11:56 +00002896 PRE_REG_READ3(long, "getdents64",
2897 unsigned int, fd, struct linux_dirent64 *, dirp,
2898 unsigned int, count);
njn22cfccb2004-11-27 16:10:23 +00002899 PRE_MEM_WRITE( "getdents64(dirp)", ARG2, ARG3 );
jsgf855d93d2003-10-13 22:26:55 +00002900}
2901
nethercote85a456f2004-11-16 17:31:56 +00002902POST(sys_getdents64)
jsgf855d93d2003-10-13 22:26:55 +00002903{
sewardja8d8e232005-06-07 20:04:56 +00002904 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00002905 if (RES > 0)
2906 POST_MEM_WRITE( ARG2, RES );
jsgf855d93d2003-10-13 22:26:55 +00002907}
2908
sewardj78b50e42005-06-08 01:47:28 +00002909PRE(sys_getgroups)
2910{
2911 PRINT("sys_getgroups ( %d, %p )", ARG1, ARG2);
2912 PRE_REG_READ2(long, "getgroups", int, size, vki_gid_t *, list);
2913 if (ARG1 > 0)
2914 PRE_MEM_WRITE( "getgroups(list)", ARG2, ARG1 * sizeof(vki_gid_t) );
2915}
2916
2917POST(sys_getgroups)
2918{
2919 vg_assert(SUCCESS);
2920 if (ARG1 > 0 && RES > 0)
2921 POST_MEM_WRITE( ARG2, RES * sizeof(vki_gid_t) );
2922}
nethercote686b5db2004-11-14 13:42:51 +00002923
sewardja8d8e232005-06-07 20:04:56 +00002924PRE(sys_getcwd)
jsgf855d93d2003-10-13 22:26:55 +00002925{
njn4b70e8c2005-08-14 17:36:07 +00002926 // Comment from linux/fs/dcache.c:
2927 // NOTE! The user-level library version returns a character pointer.
2928 // The kernel system call just returns the length of the buffer filled
2929 // (which includes the ending '\0' character), or a negative error
2930 // value.
2931 // Is this Linux-specific? If so it should be moved to syswrap-linux.c.
njn22cfccb2004-11-27 16:10:23 +00002932 PRINT("sys_getcwd ( %p, %llu )", ARG1,(ULong)ARG2);
nethercoteac866b92004-11-15 20:23:15 +00002933 PRE_REG_READ2(long, "getcwd", char *, buf, unsigned long, size);
njn22cfccb2004-11-27 16:10:23 +00002934 PRE_MEM_WRITE( "getcwd(buf)", ARG1, ARG2 );
jsgf855d93d2003-10-13 22:26:55 +00002935}
2936
nethercote85a456f2004-11-16 17:31:56 +00002937POST(sys_getcwd)
jsgf855d93d2003-10-13 22:26:55 +00002938{
sewardja8d8e232005-06-07 20:04:56 +00002939 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00002940 if (RES != (Addr)NULL)
2941 POST_MEM_WRITE( ARG1, RES );
jsgf855d93d2003-10-13 22:26:55 +00002942}
2943
sewardja8d8e232005-06-07 20:04:56 +00002944PRE(sys_geteuid)
jsgf855d93d2003-10-13 22:26:55 +00002945{
nethercote0df495a2004-11-11 16:38:21 +00002946 PRINT("sys_geteuid ( )");
2947 PRE_REG_READ0(long, "geteuid");
jsgf855d93d2003-10-13 22:26:55 +00002948}
2949
sewardj78b50e42005-06-08 01:47:28 +00002950PRE(sys_getegid)
2951{
2952 PRINT("sys_getegid ( )");
2953 PRE_REG_READ0(long, "getegid");
2954}
2955
sewardj78b50e42005-06-08 01:47:28 +00002956PRE(sys_getgid)
2957{
2958 PRINT("sys_getgid ( )");
2959 PRE_REG_READ0(long, "getgid");
2960}
jsgf855d93d2003-10-13 22:26:55 +00002961
sewardja8d8e232005-06-07 20:04:56 +00002962PRE(sys_getpid)
jsgf855d93d2003-10-13 22:26:55 +00002963{
nethercote4e632c22004-11-09 16:45:33 +00002964 PRINT("sys_getpid ()");
2965 PRE_REG_READ0(long, "getpid");
jsgf855d93d2003-10-13 22:26:55 +00002966}
2967
sewardj696c5512005-06-08 23:38:32 +00002968PRE(sys_getpgid)
2969{
2970 PRINT("sys_getpgid ( %d )", ARG1);
2971 PRE_REG_READ1(long, "getpgid", vki_pid_t, pid);
2972}
sewardj78b50e42005-06-08 01:47:28 +00002973
2974PRE(sys_getpgrp)
2975{
2976 PRINT("sys_getpgrp ()");
2977 PRE_REG_READ0(long, "getpgrp");
2978}
jsgf855d93d2003-10-13 22:26:55 +00002979
sewardja8d8e232005-06-07 20:04:56 +00002980PRE(sys_getppid)
jsgf855d93d2003-10-13 22:26:55 +00002981{
nethercote4e632c22004-11-09 16:45:33 +00002982 PRINT("sys_getppid ()");
2983 PRE_REG_READ0(long, "getppid");
jsgf855d93d2003-10-13 22:26:55 +00002984}
2985
njncf45fd42004-11-24 16:30:22 +00002986static void common_post_getrlimit(ThreadId tid, UWord a1, UWord a2)
jsgf855d93d2003-10-13 22:26:55 +00002987{
nethercote620154f2004-11-12 21:21:07 +00002988 POST_MEM_WRITE( a2, sizeof(struct vki_rlimit) );
jsgf855d93d2003-10-13 22:26:55 +00002989
nethercote620154f2004-11-12 21:21:07 +00002990 switch (a1) {
2991 case VKI_RLIMIT_NOFILE:
2992 ((struct vki_rlimit *)a2)->rlim_cur = VG_(fd_soft_limit);
2993 ((struct vki_rlimit *)a2)->rlim_max = VG_(fd_hard_limit);
2994 break;
nethercote535f03b2004-02-15 15:32:51 +00002995
nethercote620154f2004-11-12 21:21:07 +00002996 case VKI_RLIMIT_DATA:
2997 *((struct vki_rlimit *)a2) = VG_(client_rlimit_data);
2998 break;
fitzhardingeb50068f2004-02-24 23:42:55 +00002999
nethercote620154f2004-11-12 21:21:07 +00003000 case VKI_RLIMIT_STACK:
3001 *((struct vki_rlimit *)a2) = VG_(client_rlimit_stack);
3002 break;
fitzhardingeb50068f2004-02-24 23:42:55 +00003003 }
jsgf855d93d2003-10-13 22:26:55 +00003004}
3005
sewardj696c5512005-06-08 23:38:32 +00003006PRE(sys_old_getrlimit)
3007{
3008 PRINT("sys_old_getrlimit ( %d, %p )", ARG1,ARG2);
3009 PRE_REG_READ2(long, "old_getrlimit",
3010 unsigned int, resource, struct rlimit *, rlim);
3011 PRE_MEM_WRITE( "old_getrlimit(rlim)", ARG2, sizeof(struct vki_rlimit) );
3012}
3013
3014POST(sys_old_getrlimit)
3015{
3016 common_post_getrlimit(tid, ARG1, ARG2);
3017}
nethercote620154f2004-11-12 21:21:07 +00003018
sewardja8d8e232005-06-07 20:04:56 +00003019PRE(sys_getrlimit)
nethercote620154f2004-11-12 21:21:07 +00003020{
njn22cfccb2004-11-27 16:10:23 +00003021 PRINT("sys_getrlimit ( %d, %p )", ARG1,ARG2);
nethercote620154f2004-11-12 21:21:07 +00003022 PRE_REG_READ2(long, "getrlimit",
3023 unsigned int, resource, struct rlimit *, rlim);
njn22cfccb2004-11-27 16:10:23 +00003024 PRE_MEM_WRITE( "getrlimit(rlim)", ARG2, sizeof(struct vki_rlimit) );
nethercote620154f2004-11-12 21:21:07 +00003025}
3026
nethercote85a456f2004-11-16 17:31:56 +00003027POST(sys_getrlimit)
nethercote620154f2004-11-12 21:21:07 +00003028{
njn22cfccb2004-11-27 16:10:23 +00003029 common_post_getrlimit(tid, ARG1, ARG2);
nethercote620154f2004-11-12 21:21:07 +00003030}
jsgf855d93d2003-10-13 22:26:55 +00003031
sewardj696c5512005-06-08 23:38:32 +00003032PRE(sys_getrusage)
3033{
sewardj696c5512005-06-08 23:38:32 +00003034 PRINT("sys_getrusage ( %d, %p )", ARG1,ARG2);
3035 PRE_REG_READ2(long, "getrusage", int, who, struct rusage *, usage);
3036 PRE_MEM_WRITE( "getrusage(usage)", ARG2, sizeof(struct vki_rusage) );
3037}
3038
3039POST(sys_getrusage)
3040{
3041 vg_assert(SUCCESS);
3042 if (RES == 0)
3043 POST_MEM_WRITE( ARG2, sizeof(struct vki_rusage) );
3044}
jsgf855d93d2003-10-13 22:26:55 +00003045
sewardja8d8e232005-06-07 20:04:56 +00003046PRE(sys_gettimeofday)
jsgf855d93d2003-10-13 22:26:55 +00003047{
njn22cfccb2004-11-27 16:10:23 +00003048 PRINT("sys_gettimeofday ( %p, %p )", ARG1,ARG2);
nethercote686b5db2004-11-14 13:42:51 +00003049 PRE_REG_READ2(long, "gettimeofday",
3050 struct timeval *, tv, struct timezone *, tz);
njn22cfccb2004-11-27 16:10:23 +00003051 PRE_MEM_WRITE( "gettimeofday(tv)", ARG1, sizeof(struct vki_timeval) );
3052 if (ARG2 != 0)
3053 PRE_MEM_WRITE( "gettimeofday(tz)", ARG2, sizeof(struct vki_timezone) );
jsgf855d93d2003-10-13 22:26:55 +00003054}
3055
nethercote85a456f2004-11-16 17:31:56 +00003056POST(sys_gettimeofday)
jsgf855d93d2003-10-13 22:26:55 +00003057{
sewardja8d8e232005-06-07 20:04:56 +00003058 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00003059 if (RES == 0) {
3060 POST_MEM_WRITE( ARG1, sizeof(struct vki_timeval) );
3061 if (ARG2 != 0)
3062 POST_MEM_WRITE( ARG2, sizeof(struct vki_timezone) );
jsgf855d93d2003-10-13 22:26:55 +00003063 }
3064}
3065
sewardj696c5512005-06-08 23:38:32 +00003066PRE(sys_settimeofday)
3067{
3068 PRINT("sys_settimeofday ( %p, %p )", ARG1,ARG2);
3069 PRE_REG_READ2(long, "settimeofday",
3070 struct timeval *, tv, struct timezone *, tz);
3071 PRE_MEM_READ( "settimeofday(tv)", ARG1, sizeof(struct vki_timeval) );
3072 if (ARG2 != 0) {
3073 PRE_MEM_READ( "settimeofday(tz)", ARG2, sizeof(struct vki_timezone) );
3074 /* maybe should warn if tz->tz_dsttime is non-zero? */
3075 }
3076}
nethercote686b5db2004-11-14 13:42:51 +00003077
sewardja8d8e232005-06-07 20:04:56 +00003078PRE(sys_getuid)
jsgf855d93d2003-10-13 22:26:55 +00003079{
nethercote0df495a2004-11-11 16:38:21 +00003080 PRINT("sys_getuid ( )");
3081 PRE_REG_READ0(long, "getuid");
jsgf855d93d2003-10-13 22:26:55 +00003082}
3083
nethercote2e1c37d2004-11-13 13:57:12 +00003084// XXX: I reckon some of these cases must be x86-specific
sewardja8d8e232005-06-07 20:04:56 +00003085PRE(sys_ioctl)
jsgf855d93d2003-10-13 22:26:55 +00003086{
sewardja8d8e232005-06-07 20:04:56 +00003087 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00003088 PRINT("sys_ioctl ( %d, 0x%x, %p )",ARG1,ARG2,ARG3);
nethercote9c311eb2004-11-12 18:20:12 +00003089 PRE_REG_READ3(long, "ioctl",
3090 unsigned int, fd, unsigned int, request, unsigned long, arg);
3091
njn22cfccb2004-11-27 16:10:23 +00003092 switch (ARG2 /* request */) {
nethercote73b526f2004-10-31 18:48:21 +00003093 case VKI_TCSETS:
3094 case VKI_TCSETSW:
3095 case VKI_TCSETSF:
njn22cfccb2004-11-27 16:10:23 +00003096 PRE_MEM_READ( "ioctl(TCSET{S,SW,SF})", ARG3, sizeof(struct vki_termios) );
jsgf855d93d2003-10-13 22:26:55 +00003097 break;
nethercote73b526f2004-10-31 18:48:21 +00003098 case VKI_TCGETS:
njn22cfccb2004-11-27 16:10:23 +00003099 PRE_MEM_WRITE( "ioctl(TCGETS)", ARG3, sizeof(struct vki_termios) );
jsgf855d93d2003-10-13 22:26:55 +00003100 break;
nethercote73b526f2004-10-31 18:48:21 +00003101 case VKI_TCSETA:
3102 case VKI_TCSETAW:
3103 case VKI_TCSETAF:
njn22cfccb2004-11-27 16:10:23 +00003104 PRE_MEM_READ( "ioctl(TCSET{A,AW,AF})", ARG3, sizeof(struct vki_termio) );
jsgf855d93d2003-10-13 22:26:55 +00003105 break;
nethercote73b526f2004-10-31 18:48:21 +00003106 case VKI_TCGETA:
njn22cfccb2004-11-27 16:10:23 +00003107 PRE_MEM_WRITE( "ioctl(TCGETA)", ARG3, sizeof(struct vki_termio) );
jsgf855d93d2003-10-13 22:26:55 +00003108 break;
nethercote73b526f2004-10-31 18:48:21 +00003109 case VKI_TCSBRK:
3110 case VKI_TCXONC:
3111 case VKI_TCSBRKP:
3112 case VKI_TCFLSH:
jsgf855d93d2003-10-13 22:26:55 +00003113 /* These just take an int by value */
3114 break;
nethercote73b526f2004-10-31 18:48:21 +00003115 case VKI_TIOCGWINSZ:
njn22cfccb2004-11-27 16:10:23 +00003116 PRE_MEM_WRITE( "ioctl(TIOCGWINSZ)", ARG3, sizeof(struct vki_winsize) );
jsgf855d93d2003-10-13 22:26:55 +00003117 break;
nethercote73b526f2004-10-31 18:48:21 +00003118 case VKI_TIOCSWINSZ:
njn22cfccb2004-11-27 16:10:23 +00003119 PRE_MEM_READ( "ioctl(TIOCSWINSZ)", ARG3, sizeof(struct vki_winsize) );
jsgf855d93d2003-10-13 22:26:55 +00003120 break;
nethercote73b526f2004-10-31 18:48:21 +00003121 case VKI_TIOCMBIS:
njn22cfccb2004-11-27 16:10:23 +00003122 PRE_MEM_READ( "ioctl(TIOCMBIS)", ARG3, sizeof(unsigned int) );
thughesfc5cd002004-09-11 14:37:04 +00003123 break;
nethercote73b526f2004-10-31 18:48:21 +00003124 case VKI_TIOCMBIC:
njn22cfccb2004-11-27 16:10:23 +00003125 PRE_MEM_READ( "ioctl(TIOCMBIC)", ARG3, sizeof(unsigned int) );
thughesfc5cd002004-09-11 14:37:04 +00003126 break;
nethercote73b526f2004-10-31 18:48:21 +00003127 case VKI_TIOCMSET:
njn22cfccb2004-11-27 16:10:23 +00003128 PRE_MEM_READ( "ioctl(TIOCMSET)", ARG3, sizeof(unsigned int) );
thughesfc5cd002004-09-11 14:37:04 +00003129 break;
tom62ba7582005-07-28 16:26:34 +00003130 case VKI_TIOCMGET:
3131 PRE_MEM_WRITE( "ioctl(TIOCMGET)", ARG3, sizeof(unsigned int) );
3132 break;
nethercote73b526f2004-10-31 18:48:21 +00003133 case VKI_TIOCLINUX:
njn22cfccb2004-11-27 16:10:23 +00003134 PRE_MEM_READ( "ioctl(TIOCLINUX)", ARG3, sizeof(char *) );
3135 if (*(char *)ARG3 == 11) {
3136 PRE_MEM_READ( "ioctl(TIOCLINUX, 11)", ARG3, 2 * sizeof(char *) );
jsgf855d93d2003-10-13 22:26:55 +00003137 }
3138 break;
nethercote73b526f2004-10-31 18:48:21 +00003139 case VKI_TIOCGPGRP:
jsgf855d93d2003-10-13 22:26:55 +00003140 /* Get process group ID for foreground processing group. */
njn22cfccb2004-11-27 16:10:23 +00003141 PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t) );
jsgf855d93d2003-10-13 22:26:55 +00003142 break;
nethercote73b526f2004-10-31 18:48:21 +00003143 case VKI_TIOCSPGRP:
jsgf855d93d2003-10-13 22:26:55 +00003144 /* Set a process group ID? */
njn22cfccb2004-11-27 16:10:23 +00003145 PRE_MEM_WRITE( "ioctl(TIOCGPGRP)", ARG3, sizeof(vki_pid_t) );
jsgf855d93d2003-10-13 22:26:55 +00003146 break;
nethercote73b526f2004-10-31 18:48:21 +00003147 case VKI_TIOCGPTN: /* Get Pty Number (of pty-mux device) */
njn22cfccb2004-11-27 16:10:23 +00003148 PRE_MEM_WRITE( "ioctl(TIOCGPTN)", ARG3, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00003149 break;
nethercote73b526f2004-10-31 18:48:21 +00003150 case VKI_TIOCSCTTY:
jsgf855d93d2003-10-13 22:26:55 +00003151 /* Just takes an int value. */
3152 break;
nethercote73b526f2004-10-31 18:48:21 +00003153 case VKI_TIOCSPTLCK: /* Lock/unlock Pty */
njn22cfccb2004-11-27 16:10:23 +00003154 PRE_MEM_READ( "ioctl(TIOCSPTLCK)", ARG3, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00003155 break;
nethercote73b526f2004-10-31 18:48:21 +00003156 case VKI_FIONBIO:
njn22cfccb2004-11-27 16:10:23 +00003157 PRE_MEM_READ( "ioctl(FIONBIO)", ARG3, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00003158 break;
nethercote73b526f2004-10-31 18:48:21 +00003159 case VKI_FIOASYNC:
njn22cfccb2004-11-27 16:10:23 +00003160 PRE_MEM_READ( "ioctl(FIOASYNC)", ARG3, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00003161 break;
nethercote73b526f2004-10-31 18:48:21 +00003162 case VKI_FIONREAD: /* identical to SIOCINQ */
njn22cfccb2004-11-27 16:10:23 +00003163 PRE_MEM_WRITE( "ioctl(FIONREAD)", ARG3, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00003164 break;
3165
nethercote73b526f2004-10-31 18:48:21 +00003166 case VKI_SG_SET_COMMAND_Q:
njn22cfccb2004-11-27 16:10:23 +00003167 PRE_MEM_READ( "ioctl(SG_SET_COMMAND_Q)", ARG3, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00003168 break;
nethercote73b526f2004-10-31 18:48:21 +00003169 case VKI_SG_IO:
njn22cfccb2004-11-27 16:10:23 +00003170 PRE_MEM_WRITE( "ioctl(SG_IO)", ARG3, sizeof(vki_sg_io_hdr_t) );
jsgf855d93d2003-10-13 22:26:55 +00003171 break;
nethercote73b526f2004-10-31 18:48:21 +00003172 case VKI_SG_GET_SCSI_ID:
njn22cfccb2004-11-27 16:10:23 +00003173 PRE_MEM_WRITE( "ioctl(SG_GET_SCSI_ID)", ARG3, sizeof(vki_sg_scsi_id_t) );
jsgf855d93d2003-10-13 22:26:55 +00003174 break;
nethercote73b526f2004-10-31 18:48:21 +00003175 case VKI_SG_SET_RESERVED_SIZE:
njn22cfccb2004-11-27 16:10:23 +00003176 PRE_MEM_READ( "ioctl(SG_SET_RESERVED_SIZE)", ARG3, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00003177 break;
nethercote73b526f2004-10-31 18:48:21 +00003178 case VKI_SG_SET_TIMEOUT:
njn22cfccb2004-11-27 16:10:23 +00003179 PRE_MEM_READ( "ioctl(SG_SET_TIMEOUT)", ARG3, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00003180 break;
nethercote73b526f2004-10-31 18:48:21 +00003181 case VKI_SG_GET_RESERVED_SIZE:
njn22cfccb2004-11-27 16:10:23 +00003182 PRE_MEM_WRITE( "ioctl(SG_GET_RESERVED_SIZE)", ARG3, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00003183 break;
nethercote73b526f2004-10-31 18:48:21 +00003184 case VKI_SG_GET_TIMEOUT:
njn22cfccb2004-11-27 16:10:23 +00003185 PRE_MEM_WRITE( "ioctl(SG_GET_TIMEOUT)", ARG3, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00003186 break;
nethercote73b526f2004-10-31 18:48:21 +00003187 case VKI_SG_GET_VERSION_NUM:
njn22cfccb2004-11-27 16:10:23 +00003188 PRE_MEM_READ( "ioctl(SG_GET_VERSION_NUM)", ARG3, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00003189 break;
nethercote73b526f2004-10-31 18:48:21 +00003190 case VKI_SG_EMULATED_HOST: /* 0x2203 */
njn22cfccb2004-11-27 16:10:23 +00003191 PRE_MEM_WRITE( "ioctl(SG_EMULATED_HOST)", ARG3, sizeof(int) );
thughes5b788fb2004-09-11 15:07:14 +00003192 break;
nethercote73b526f2004-10-31 18:48:21 +00003193 case VKI_SG_GET_SG_TABLESIZE: /* 0x227f */
njn22cfccb2004-11-27 16:10:23 +00003194 PRE_MEM_WRITE( "ioctl(SG_GET_SG_TABLESIZE)", ARG3, sizeof(int) );
thughes5b788fb2004-09-11 15:07:14 +00003195 break;
jsgf855d93d2003-10-13 22:26:55 +00003196
muellera4b153a2003-11-19 22:07:14 +00003197 case VKI_IIOCGETCPS:
njn22cfccb2004-11-27 16:10:23 +00003198 PRE_MEM_WRITE( "ioctl(IIOCGETCPS)", ARG3,
nethercote95a97862004-11-06 16:31:43 +00003199 VKI_ISDN_MAX_CHANNELS * 2 * sizeof(unsigned long) );
jsgf855d93d2003-10-13 22:26:55 +00003200 break;
muellera4b153a2003-11-19 22:07:14 +00003201 case VKI_IIOCNETGPN:
nethercoteef0c7662004-11-06 15:38:43 +00003202 PRE_MEM_READ( "ioctl(IIOCNETGPN)",
njn22cfccb2004-11-27 16:10:23 +00003203 (Addr)&((vki_isdn_net_ioctl_phone *)ARG3)->name,
3204 sizeof(((vki_isdn_net_ioctl_phone *)ARG3)->name) );
3205 PRE_MEM_WRITE( "ioctl(IIOCNETGPN)", ARG3,
nethercote73b526f2004-10-31 18:48:21 +00003206 sizeof(vki_isdn_net_ioctl_phone) );
jsgf855d93d2003-10-13 22:26:55 +00003207 break;
3208
3209 /* These all use struct ifreq AFAIK */
nethercote73b526f2004-10-31 18:48:21 +00003210 case VKI_SIOCGIFINDEX: /* get iface index */
nethercoteef0c7662004-11-06 15:38:43 +00003211 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFINDEX)",
njn22cfccb2004-11-27 16:10:23 +00003212 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
3213 PRE_MEM_WRITE( "ioctl(SIOCGIFINDEX)", ARG3, sizeof(struct vki_ifreq));
jsgf855d93d2003-10-13 22:26:55 +00003214 break;
nethercote73b526f2004-10-31 18:48:21 +00003215 case VKI_SIOCGIFFLAGS: /* get flags */
nethercoteef0c7662004-11-06 15:38:43 +00003216 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFFLAGS)",
njn22cfccb2004-11-27 16:10:23 +00003217 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
3218 PRE_MEM_WRITE( "ioctl(SIOCGIFFLAGS)", ARG3, sizeof(struct vki_ifreq));
thughesbe811712004-06-17 23:04:58 +00003219 break;
nethercote73b526f2004-10-31 18:48:21 +00003220 case VKI_SIOCGIFHWADDR: /* Get hardware address */
nethercoteef0c7662004-11-06 15:38:43 +00003221 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFHWADDR)",
njn22cfccb2004-11-27 16:10:23 +00003222 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
3223 PRE_MEM_WRITE( "ioctl(SIOCGIFHWADDR)", ARG3, sizeof(struct vki_ifreq));
thughesbe811712004-06-17 23:04:58 +00003224 break;
nethercote73b526f2004-10-31 18:48:21 +00003225 case VKI_SIOCGIFMTU: /* get MTU size */
nethercoteef0c7662004-11-06 15:38:43 +00003226 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMTU)",
njn22cfccb2004-11-27 16:10:23 +00003227 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
3228 PRE_MEM_WRITE( "ioctl(SIOCGIFMTU)", ARG3, sizeof(struct vki_ifreq));
thughesbe811712004-06-17 23:04:58 +00003229 break;
nethercote73b526f2004-10-31 18:48:21 +00003230 case VKI_SIOCGIFADDR: /* get PA address */
nethercoteef0c7662004-11-06 15:38:43 +00003231 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFADDR)",
njn22cfccb2004-11-27 16:10:23 +00003232 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
3233 PRE_MEM_WRITE( "ioctl(SIOCGIFADDR)", ARG3, sizeof(struct vki_ifreq));
thughesbe811712004-06-17 23:04:58 +00003234 break;
nethercote73b526f2004-10-31 18:48:21 +00003235 case VKI_SIOCGIFNETMASK: /* get network PA mask */
nethercoteef0c7662004-11-06 15:38:43 +00003236 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFNETMASK)",
njn22cfccb2004-11-27 16:10:23 +00003237 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
3238 PRE_MEM_WRITE( "ioctl(SIOCGIFNETMASK)", ARG3, sizeof(struct vki_ifreq));
thughesbe811712004-06-17 23:04:58 +00003239 break;
nethercote73b526f2004-10-31 18:48:21 +00003240 case VKI_SIOCGIFMETRIC: /* get metric */
nethercoteef0c7662004-11-06 15:38:43 +00003241 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMETRIC)",
njn22cfccb2004-11-27 16:10:23 +00003242 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
3243 PRE_MEM_WRITE( "ioctl(SIOCGIFMETRIC)", ARG3, sizeof(struct vki_ifreq));
thughesbe811712004-06-17 23:04:58 +00003244 break;
nethercote73b526f2004-10-31 18:48:21 +00003245 case VKI_SIOCGIFMAP: /* Get device parameters */
nethercoteef0c7662004-11-06 15:38:43 +00003246 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMAP)",
njn22cfccb2004-11-27 16:10:23 +00003247 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
3248 PRE_MEM_WRITE( "ioctl(SIOCGIFMAP)", ARG3, sizeof(struct vki_ifreq));
thughesbe811712004-06-17 23:04:58 +00003249 break;
nethercote73b526f2004-10-31 18:48:21 +00003250 case VKI_SIOCGIFTXQLEN: /* Get the tx queue length */
nethercoteef0c7662004-11-06 15:38:43 +00003251 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFTXQLEN)",
njn22cfccb2004-11-27 16:10:23 +00003252 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
3253 PRE_MEM_WRITE( "ioctl(SIOCGIFTXQLEN)", ARG3, sizeof(struct vki_ifreq));
thughesbe811712004-06-17 23:04:58 +00003254 break;
nethercote73b526f2004-10-31 18:48:21 +00003255 case VKI_SIOCGIFDSTADDR: /* get remote PA address */
nethercoteef0c7662004-11-06 15:38:43 +00003256 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFDSTADDR)",
njn22cfccb2004-11-27 16:10:23 +00003257 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
3258 PRE_MEM_WRITE( "ioctl(SIOCGIFDSTADDR)", ARG3, sizeof(struct vki_ifreq));
thughesbe811712004-06-17 23:04:58 +00003259 break;
nethercote73b526f2004-10-31 18:48:21 +00003260 case VKI_SIOCGIFBRDADDR: /* get broadcast PA address */
nethercoteef0c7662004-11-06 15:38:43 +00003261 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFBRDADDR)",
njn22cfccb2004-11-27 16:10:23 +00003262 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
3263 PRE_MEM_WRITE( "ioctl(SIOCGIFBRDADDR)", ARG3, sizeof(struct vki_ifreq));
thughesbe811712004-06-17 23:04:58 +00003264 break;
nethercote73b526f2004-10-31 18:48:21 +00003265 case VKI_SIOCGIFNAME: /* get iface name */
nethercoteef0c7662004-11-06 15:38:43 +00003266 PRE_MEM_READ( "ioctl(SIOCGIFNAME)",
tom3b86ae52005-07-29 18:42:22 +00003267 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_ifindex,
njn22cfccb2004-11-27 16:10:23 +00003268 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_ifindex) );
3269 PRE_MEM_WRITE( "ioctl(SIOCGIFNAME)", ARG3, sizeof(struct vki_ifreq));
thughesbe811712004-06-17 23:04:58 +00003270 break;
nethercote73b526f2004-10-31 18:48:21 +00003271 case VKI_SIOCGMIIPHY: /* get hardware entry */
nethercoteef0c7662004-11-06 15:38:43 +00003272 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMIIPHY)",
njn22cfccb2004-11-27 16:10:23 +00003273 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
3274 PRE_MEM_WRITE( "ioctl(SIOCGIFMIIPHY)", ARG3, sizeof(struct vki_ifreq));
thughesbe811712004-06-17 23:04:58 +00003275 break;
nethercote73b526f2004-10-31 18:48:21 +00003276 case VKI_SIOCGMIIREG: /* get hardware entry registers */
nethercoteef0c7662004-11-06 15:38:43 +00003277 PRE_MEM_RASCIIZ( "ioctl(SIOCGIFMIIREG)",
njn22cfccb2004-11-27 16:10:23 +00003278 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
nethercoteef0c7662004-11-06 15:38:43 +00003279 PRE_MEM_READ( "ioctl(SIOCGIFMIIREG)",
njn22cfccb2004-11-27 16:10:23 +00003280 (Addr)&((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->phy_id,
3281 sizeof(((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->phy_id) );
nethercoteef0c7662004-11-06 15:38:43 +00003282 PRE_MEM_READ( "ioctl(SIOCGIFMIIREG)",
njn22cfccb2004-11-27 16:10:23 +00003283 (Addr)&((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->reg_num,
3284 sizeof(((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->reg_num) );
3285 PRE_MEM_WRITE( "ioctl(SIOCGIFMIIREG)", ARG3,
nethercote73b526f2004-10-31 18:48:21 +00003286 sizeof(struct vki_ifreq));
thughesbe811712004-06-17 23:04:58 +00003287 break;
nethercote73b526f2004-10-31 18:48:21 +00003288 case VKI_SIOCGIFCONF: /* get iface list */
jsgf855d93d2003-10-13 22:26:55 +00003289 /* WAS:
njn22cfccb2004-11-27 16:10:23 +00003290 PRE_MEM_WRITE( "ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf));
3291 KERNEL_DO_SYSCALL(tid,RES);
3292 if (!VG_(is_kerror)(RES) && RES == 0)
3293 POST_MEM_WRITE(ARG3, sizeof(struct ifconf));
jsgf855d93d2003-10-13 22:26:55 +00003294 */
tomb9fef192005-07-18 22:45:55 +00003295 PRE_MEM_READ( "ioctl(SIOCGIFCONF)",
3296 (Addr)&((struct vki_ifconf *)ARG3)->ifc_len,
3297 sizeof(((struct vki_ifconf *)ARG3)->ifc_len));
3298 PRE_MEM_READ( "ioctl(SIOCGIFCONF)",
3299 (Addr)&((struct vki_ifconf *)ARG3)->vki_ifc_buf,
3300 sizeof(((struct vki_ifconf *)ARG3)->vki_ifc_buf));
njn22cfccb2004-11-27 16:10:23 +00003301 if ( ARG3 ) {
jsgf855d93d2003-10-13 22:26:55 +00003302 // TODO len must be readable and writable
3303 // buf pointer only needs to be readable
njn22cfccb2004-11-27 16:10:23 +00003304 struct vki_ifconf *ifc = (struct vki_ifconf *) ARG3;
nethercoteef0c7662004-11-06 15:38:43 +00003305 PRE_MEM_WRITE( "ioctl(SIOCGIFCONF).ifc_buf",
nethercote50397c22004-11-04 18:03:06 +00003306 (Addr)(ifc->vki_ifc_buf), ifc->ifc_len );
jsgf855d93d2003-10-13 22:26:55 +00003307 }
3308 break;
nethercote73b526f2004-10-31 18:48:21 +00003309 case VKI_SIOCGSTAMP:
njn22cfccb2004-11-27 16:10:23 +00003310 PRE_MEM_WRITE( "ioctl(SIOCGSTAMP)", ARG3, sizeof(struct vki_timeval));
jsgf855d93d2003-10-13 22:26:55 +00003311 break;
3312 /* SIOCOUTQ is an ioctl that, when called on a socket, returns
3313 the number of bytes currently in that socket's send buffer.
3314 It writes this value as an int to the memory location
3315 indicated by the third argument of ioctl(2). */
nethercote73b526f2004-10-31 18:48:21 +00003316 case VKI_SIOCOUTQ:
njn22cfccb2004-11-27 16:10:23 +00003317 PRE_MEM_WRITE( "ioctl(SIOCOUTQ)", ARG3, sizeof(int));
jsgf855d93d2003-10-13 22:26:55 +00003318 break;
nethercote73b526f2004-10-31 18:48:21 +00003319 case VKI_SIOCGRARP: /* get RARP table entry */
3320 case VKI_SIOCGARP: /* get ARP table entry */
njn22cfccb2004-11-27 16:10:23 +00003321 PRE_MEM_WRITE( "ioctl(SIOCGARP)", ARG3, sizeof(struct vki_arpreq));
jsgf855d93d2003-10-13 22:26:55 +00003322 break;
3323
nethercote73b526f2004-10-31 18:48:21 +00003324 case VKI_SIOCSIFFLAGS: /* set flags */
nethercoteef0c7662004-11-06 15:38:43 +00003325 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFFLAGS)",
njn22cfccb2004-11-27 16:10:23 +00003326 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
nethercoteef0c7662004-11-06 15:38:43 +00003327 PRE_MEM_READ( "ioctl(SIOCSIFFLAGS)",
njn22cfccb2004-11-27 16:10:23 +00003328 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_flags,
3329 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_flags) );
thughesbe811712004-06-17 23:04:58 +00003330 break;
nethercote73b526f2004-10-31 18:48:21 +00003331 case VKI_SIOCSIFMAP: /* Set device parameters */
nethercoteef0c7662004-11-06 15:38:43 +00003332 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMAP)",
njn22cfccb2004-11-27 16:10:23 +00003333 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
nethercoteef0c7662004-11-06 15:38:43 +00003334 PRE_MEM_READ( "ioctl(SIOCSIFMAP)",
njn22cfccb2004-11-27 16:10:23 +00003335 (Addr)&((struct vki_ifreq *)ARG3)->ifr_map,
3336 sizeof(((struct vki_ifreq *)ARG3)->ifr_map) );
thughesbe811712004-06-17 23:04:58 +00003337 break;
nethercote73b526f2004-10-31 18:48:21 +00003338 case VKI_SIOCSIFTXQLEN: /* Set the tx queue length */
nethercoteef0c7662004-11-06 15:38:43 +00003339 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFTXQLEN)",
njn22cfccb2004-11-27 16:10:23 +00003340 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
nethercoteef0c7662004-11-06 15:38:43 +00003341 PRE_MEM_READ( "ioctl(SIOCSIFTXQLEN)",
njn22cfccb2004-11-27 16:10:23 +00003342 (Addr)&((struct vki_ifreq *)ARG3)->ifr_qlen,
3343 sizeof(((struct vki_ifreq *)ARG3)->ifr_qlen) );
thughesbe811712004-06-17 23:04:58 +00003344 break;
nethercote73b526f2004-10-31 18:48:21 +00003345 case VKI_SIOCSIFADDR: /* set PA address */
3346 case VKI_SIOCSIFDSTADDR: /* set remote PA address */
3347 case VKI_SIOCSIFBRDADDR: /* set broadcast PA address */
3348 case VKI_SIOCSIFNETMASK: /* set network PA mask */
nethercoteef0c7662004-11-06 15:38:43 +00003349 PRE_MEM_RASCIIZ( "ioctl(SIOCSIF*ADDR)",
njn22cfccb2004-11-27 16:10:23 +00003350 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
nethercoteef0c7662004-11-06 15:38:43 +00003351 PRE_MEM_READ( "ioctl(SIOCSIF*ADDR)",
njn22cfccb2004-11-27 16:10:23 +00003352 (Addr)&((struct vki_ifreq *)ARG3)->ifr_addr,
3353 sizeof(((struct vki_ifreq *)ARG3)->ifr_addr) );
jsgf855d93d2003-10-13 22:26:55 +00003354 break;
nethercote73b526f2004-10-31 18:48:21 +00003355 case VKI_SIOCSIFMETRIC: /* set metric */
nethercoteef0c7662004-11-06 15:38:43 +00003356 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMETRIC)",
njn22cfccb2004-11-27 16:10:23 +00003357 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
nethercoteef0c7662004-11-06 15:38:43 +00003358 PRE_MEM_READ( "ioctl(SIOCSIFMETRIC)",
njn22cfccb2004-11-27 16:10:23 +00003359 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_metric,
3360 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_metric) );
thughesbe811712004-06-17 23:04:58 +00003361 break;
nethercote73b526f2004-10-31 18:48:21 +00003362 case VKI_SIOCSIFMTU: /* set MTU size */
nethercoteef0c7662004-11-06 15:38:43 +00003363 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFMTU)",
njn22cfccb2004-11-27 16:10:23 +00003364 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
nethercoteef0c7662004-11-06 15:38:43 +00003365 PRE_MEM_READ( "ioctl(SIOCSIFMTU)",
njn22cfccb2004-11-27 16:10:23 +00003366 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_mtu,
3367 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_mtu) );
thughesbe811712004-06-17 23:04:58 +00003368 break;
nethercote73b526f2004-10-31 18:48:21 +00003369 case VKI_SIOCSIFHWADDR: /* set hardware address */
nethercoteef0c7662004-11-06 15:38:43 +00003370 PRE_MEM_RASCIIZ( "ioctl(SIOCSIFHWADDR)",
njn22cfccb2004-11-27 16:10:23 +00003371 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
nethercoteef0c7662004-11-06 15:38:43 +00003372 PRE_MEM_READ( "ioctl(SIOCSIFHWADDR)",
njn22cfccb2004-11-27 16:10:23 +00003373 (Addr)&((struct vki_ifreq *)ARG3)->ifr_hwaddr,
3374 sizeof(((struct vki_ifreq *)ARG3)->ifr_hwaddr) );
thughesbe811712004-06-17 23:04:58 +00003375 break;
nethercote73b526f2004-10-31 18:48:21 +00003376 case VKI_SIOCSMIIREG: /* set hardware entry registers */
nethercoteef0c7662004-11-06 15:38:43 +00003377 PRE_MEM_RASCIIZ( "ioctl(SIOCSMIIREG)",
njn22cfccb2004-11-27 16:10:23 +00003378 (Addr)((struct vki_ifreq *)ARG3)->vki_ifr_name );
nethercoteef0c7662004-11-06 15:38:43 +00003379 PRE_MEM_READ( "ioctl(SIOCSMIIREG)",
njn22cfccb2004-11-27 16:10:23 +00003380 (Addr)&((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->phy_id,
3381 sizeof(((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->phy_id) );
nethercoteef0c7662004-11-06 15:38:43 +00003382 PRE_MEM_READ( "ioctl(SIOCSMIIREG)",
njn22cfccb2004-11-27 16:10:23 +00003383 (Addr)&((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->reg_num,
3384 sizeof(((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->reg_num) );
nethercoteef0c7662004-11-06 15:38:43 +00003385 PRE_MEM_READ( "ioctl(SIOCSMIIREG)",
njn22cfccb2004-11-27 16:10:23 +00003386 (Addr)&((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->val_in,
3387 sizeof(((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->val_in) );
thughesbe811712004-06-17 23:04:58 +00003388 break;
jsgf855d93d2003-10-13 22:26:55 +00003389 /* Routing table calls. */
nethercote73b526f2004-10-31 18:48:21 +00003390 case VKI_SIOCADDRT: /* add routing table entry */
3391 case VKI_SIOCDELRT: /* delete routing table entry */
njn22cfccb2004-11-27 16:10:23 +00003392 PRE_MEM_READ( "ioctl(SIOCADDRT/DELRT)", ARG3,
nethercoteef0c7662004-11-06 15:38:43 +00003393 sizeof(struct vki_rtentry));
jsgf855d93d2003-10-13 22:26:55 +00003394 break;
3395
3396 /* RARP cache control calls. */
nethercote73b526f2004-10-31 18:48:21 +00003397 case VKI_SIOCDRARP: /* delete RARP table entry */
3398 case VKI_SIOCSRARP: /* set RARP table entry */
jsgf855d93d2003-10-13 22:26:55 +00003399 /* ARP cache control calls. */
nethercote73b526f2004-10-31 18:48:21 +00003400 case VKI_SIOCSARP: /* set ARP table entry */
3401 case VKI_SIOCDARP: /* delete ARP table entry */
njn22cfccb2004-11-27 16:10:23 +00003402 PRE_MEM_READ( "ioctl(SIOCSIFFLAGS)", ARG3, sizeof(struct vki_ifreq));
jsgf855d93d2003-10-13 22:26:55 +00003403 break;
3404
nethercote73b526f2004-10-31 18:48:21 +00003405 case VKI_SIOCGPGRP:
njn22cfccb2004-11-27 16:10:23 +00003406 PRE_MEM_WRITE( "ioctl(SIOCGPGRP)", ARG3, sizeof(int) );
thughes1174fed2004-09-11 15:33:17 +00003407 break;
nethercote73b526f2004-10-31 18:48:21 +00003408 case VKI_SIOCSPGRP:
njn22cfccb2004-11-27 16:10:23 +00003409 PRE_MEM_READ( "ioctl(SIOCSPGRP)", ARG3, sizeof(int) );
sewardja8d8e232005-06-07 20:04:56 +00003410 //tst->sys_flags &= ~SfMayBlock;
jsgf855d93d2003-10-13 22:26:55 +00003411 break;
3412
3413 /* linux/soundcard interface (OSS) */
nethercote73b526f2004-10-31 18:48:21 +00003414 case VKI_SNDCTL_SEQ_GETOUTCOUNT:
3415 case VKI_SNDCTL_SEQ_GETINCOUNT:
3416 case VKI_SNDCTL_SEQ_PERCMODE:
3417 case VKI_SNDCTL_SEQ_TESTMIDI:
3418 case VKI_SNDCTL_SEQ_RESETSAMPLES:
3419 case VKI_SNDCTL_SEQ_NRSYNTHS:
3420 case VKI_SNDCTL_SEQ_NRMIDIS:
3421 case VKI_SNDCTL_SEQ_GETTIME:
3422 case VKI_SNDCTL_DSP_GETFMTS:
3423 case VKI_SNDCTL_DSP_GETTRIGGER:
3424 case VKI_SNDCTL_DSP_GETODELAY:
nethercote73b526f2004-10-31 18:48:21 +00003425 case VKI_SNDCTL_DSP_GETSPDIF:
nethercote73b526f2004-10-31 18:48:21 +00003426 case VKI_SNDCTL_DSP_GETCAPS:
3427 case VKI_SOUND_PCM_READ_RATE:
3428 case VKI_SOUND_PCM_READ_CHANNELS:
3429 case VKI_SOUND_PCM_READ_BITS:
cerion85665ca2005-06-20 15:51:07 +00003430#if !defined(VGA_ppc32)
nethercote73b526f2004-10-31 18:48:21 +00003431 case (VKI_SOUND_PCM_READ_BITS|0x40000000): /* what the fuck ? */
cerion85665ca2005-06-20 15:51:07 +00003432#endif
nethercote73b526f2004-10-31 18:48:21 +00003433 case VKI_SOUND_PCM_READ_FILTER:
nethercoteef0c7662004-11-06 15:38:43 +00003434 PRE_MEM_WRITE( "ioctl(SNDCTL_XXX|SOUND_XXX (SIOR, int))",
njn22cfccb2004-11-27 16:10:23 +00003435 ARG3, sizeof(int));
jsgf855d93d2003-10-13 22:26:55 +00003436 break;
nethercote73b526f2004-10-31 18:48:21 +00003437 case VKI_SNDCTL_SEQ_CTRLRATE:
3438 case VKI_SNDCTL_DSP_SPEED:
3439 case VKI_SNDCTL_DSP_STEREO:
3440 case VKI_SNDCTL_DSP_GETBLKSIZE:
3441 case VKI_SNDCTL_DSP_CHANNELS:
3442 case VKI_SOUND_PCM_WRITE_FILTER:
3443 case VKI_SNDCTL_DSP_SUBDIVIDE:
3444 case VKI_SNDCTL_DSP_SETFRAGMENT:
nethercote73b526f2004-10-31 18:48:21 +00003445 case VKI_SNDCTL_DSP_GETCHANNELMASK:
nethercote73b526f2004-10-31 18:48:21 +00003446 case VKI_SNDCTL_DSP_BIND_CHANNEL:
nethercote73b526f2004-10-31 18:48:21 +00003447 case VKI_SNDCTL_TMR_TIMEBASE:
3448 case VKI_SNDCTL_TMR_TEMPO:
3449 case VKI_SNDCTL_TMR_SOURCE:
3450 case VKI_SNDCTL_MIDI_PRETIME:
3451 case VKI_SNDCTL_MIDI_MPUMODE:
nethercoteef0c7662004-11-06 15:38:43 +00003452 PRE_MEM_READ( "ioctl(SNDCTL_XXX|SOUND_XXX (SIOWR, int))",
njn22cfccb2004-11-27 16:10:23 +00003453 ARG3, sizeof(int));
nethercoteef0c7662004-11-06 15:38:43 +00003454 PRE_MEM_WRITE( "ioctl(SNDCTL_XXX|SOUND_XXX (SIOWR, int))",
njn22cfccb2004-11-27 16:10:23 +00003455 ARG3, sizeof(int));
jsgf855d93d2003-10-13 22:26:55 +00003456 break;
nethercote73b526f2004-10-31 18:48:21 +00003457 case VKI_SNDCTL_DSP_GETOSPACE:
3458 case VKI_SNDCTL_DSP_GETISPACE:
nethercoteef0c7662004-11-06 15:38:43 +00003459 PRE_MEM_WRITE( "ioctl(SNDCTL_XXX|SOUND_XXX (SIOR, audio_buf_info))",
njn22cfccb2004-11-27 16:10:23 +00003460 ARG3, sizeof(vki_audio_buf_info));
jsgf855d93d2003-10-13 22:26:55 +00003461 break;
nethercote73b526f2004-10-31 18:48:21 +00003462 case VKI_SNDCTL_DSP_SETTRIGGER:
nethercoteef0c7662004-11-06 15:38:43 +00003463 PRE_MEM_READ( "ioctl(SNDCTL_XXX|SOUND_XXX (SIOW, int))",
njn22cfccb2004-11-27 16:10:23 +00003464 ARG3, sizeof(int));
jsgf855d93d2003-10-13 22:26:55 +00003465 break;
3466
nethercote73b526f2004-10-31 18:48:21 +00003467 case VKI_SNDCTL_DSP_POST:
3468 case VKI_SNDCTL_DSP_RESET:
3469 case VKI_SNDCTL_DSP_SYNC:
3470 case VKI_SNDCTL_DSP_SETSYNCRO:
3471 case VKI_SNDCTL_DSP_SETDUPLEX:
jsgf855d93d2003-10-13 22:26:55 +00003472 break;
3473
tom2f932882005-11-14 17:03:54 +00003474 /* linux/soundcard interface (ALSA) */
3475 case VKI_SNDRV_PCM_IOCTL_HW_FREE:
3476 case VKI_SNDRV_PCM_IOCTL_HWSYNC:
3477 case VKI_SNDRV_PCM_IOCTL_PREPARE:
3478 case VKI_SNDRV_PCM_IOCTL_RESET:
3479 case VKI_SNDRV_PCM_IOCTL_START:
3480 case VKI_SNDRV_PCM_IOCTL_DROP:
3481 case VKI_SNDRV_PCM_IOCTL_DRAIN:
3482 case VKI_SNDRV_PCM_IOCTL_RESUME:
3483 case VKI_SNDRV_PCM_IOCTL_XRUN:
3484 case VKI_SNDRV_PCM_IOCTL_UNLINK:
3485 case VKI_SNDRV_TIMER_IOCTL_START:
3486 case VKI_SNDRV_TIMER_IOCTL_STOP:
3487 case VKI_SNDRV_TIMER_IOCTL_CONTINUE:
3488 case VKI_SNDRV_TIMER_IOCTL_PAUSE:
3489 break;
3490
jsgf855d93d2003-10-13 22:26:55 +00003491 /* Real Time Clock (/dev/rtc) ioctls */
nethercote73b526f2004-10-31 18:48:21 +00003492 case VKI_RTC_UIE_ON:
3493 case VKI_RTC_UIE_OFF:
3494 case VKI_RTC_AIE_ON:
3495 case VKI_RTC_AIE_OFF:
3496 case VKI_RTC_PIE_ON:
3497 case VKI_RTC_PIE_OFF:
3498 case VKI_RTC_IRQP_SET:
jsgf855d93d2003-10-13 22:26:55 +00003499 break;
nethercote73b526f2004-10-31 18:48:21 +00003500 case VKI_RTC_RD_TIME:
3501 case VKI_RTC_ALM_READ:
nethercoteef0c7662004-11-06 15:38:43 +00003502 PRE_MEM_WRITE( "ioctl(RTC_RD_TIME/ALM_READ)",
njn22cfccb2004-11-27 16:10:23 +00003503 ARG3, sizeof(struct vki_rtc_time));
jsgf855d93d2003-10-13 22:26:55 +00003504 break;
nethercote73b526f2004-10-31 18:48:21 +00003505 case VKI_RTC_ALM_SET:
njn22cfccb2004-11-27 16:10:23 +00003506 PRE_MEM_READ( "ioctl(RTC_ALM_SET)", ARG3, sizeof(struct vki_rtc_time));
jsgf855d93d2003-10-13 22:26:55 +00003507 break;
nethercote73b526f2004-10-31 18:48:21 +00003508 case VKI_RTC_IRQP_READ:
njn22cfccb2004-11-27 16:10:23 +00003509 PRE_MEM_WRITE( "ioctl(RTC_IRQP_READ)", ARG3, sizeof(unsigned long));
jsgf855d93d2003-10-13 22:26:55 +00003510 break;
jsgf855d93d2003-10-13 22:26:55 +00003511
tomeafc49b2005-07-28 16:08:09 +00003512 /* Block devices */
3513 case VKI_BLKROSET:
3514 PRE_MEM_READ( "ioctl(BLKROSET)", ARG3, sizeof(int));
3515 break;
3516 case VKI_BLKROGET:
3517 PRE_MEM_WRITE( "ioctl(BLKROGET)", ARG3, sizeof(int));
3518 break;
nethercote95a97862004-11-06 16:31:43 +00003519 case VKI_BLKGETSIZE:
njn22cfccb2004-11-27 16:10:23 +00003520 PRE_MEM_WRITE( "ioctl(BLKGETSIZE)", ARG3, sizeof(unsigned long));
jsgf855d93d2003-10-13 22:26:55 +00003521 break;
tomeafc49b2005-07-28 16:08:09 +00003522 case VKI_BLKRASET:
3523 break;
3524 case VKI_BLKRAGET:
3525 PRE_MEM_WRITE( "ioctl(BLKRAGET)", ARG3, sizeof(long));
3526 break;
3527 case VKI_BLKFRASET:
3528 break;
3529 case VKI_BLKFRAGET:
3530 PRE_MEM_WRITE( "ioctl(BLKFRAGET)", ARG3, sizeof(long));
3531 break;
3532 case VKI_BLKSECTGET:
3533 PRE_MEM_WRITE( "ioctl(BLKSECTGET)", ARG3, sizeof(unsigned short));
3534 break;
3535 case VKI_BLKSSZGET:
3536 PRE_MEM_WRITE( "ioctl(BLKSSZGET)", ARG3, sizeof(int));
3537 break;
3538 case VKI_BLKBSZGET:
3539 PRE_MEM_WRITE( "ioctl(BLKBSZGET)", ARG3, sizeof(int));
3540 break;
3541 case VKI_BLKBSZSET:
3542 PRE_MEM_READ( "ioctl(BLKBSZSET)", ARG3, sizeof(int));
3543 break;
tomd6555642005-07-18 13:26:55 +00003544 case VKI_BLKGETSIZE64:
3545 PRE_MEM_WRITE( "ioctl(BLKGETSIZE64)", ARG3, sizeof(unsigned long long));
3546 break;
jsgf855d93d2003-10-13 22:26:55 +00003547
thughesacbbc322004-06-19 12:12:01 +00003548 /* Hard disks */
tom2c2bc252005-07-28 16:13:42 +00003549 case VKI_HDIO_GETGEO: /* 0x0301 */
3550 PRE_MEM_WRITE( "ioctl(HDIO_GETGEO)", ARG3, sizeof(struct vki_hd_geometry));
3551 break;
nethercote73b526f2004-10-31 18:48:21 +00003552 case VKI_HDIO_GET_IDENTITY: /* 0x030d */
njn22cfccb2004-11-27 16:10:23 +00003553 PRE_MEM_WRITE( "ioctl(HDIO_GET_IDENTITY)", ARG3,
nethercote73b526f2004-10-31 18:48:21 +00003554 VKI_SIZEOF_STRUCT_HD_DRIVEID );
thughesacbbc322004-06-19 12:12:01 +00003555 break;
3556
jsgf855d93d2003-10-13 22:26:55 +00003557 /* CD ROM stuff (??) */
nethercote73b526f2004-10-31 18:48:21 +00003558 case VKI_CDROM_GET_MCN:
njn22cfccb2004-11-27 16:10:23 +00003559 PRE_MEM_READ( "ioctl(CDROM_GET_MCN)", ARG3,
nethercote73b526f2004-10-31 18:48:21 +00003560 sizeof(struct vki_cdrom_mcn) );
nethercote671398c2004-02-22 18:08:04 +00003561 break;
nethercote73b526f2004-10-31 18:48:21 +00003562 case VKI_CDROM_SEND_PACKET:
njn22cfccb2004-11-27 16:10:23 +00003563 PRE_MEM_READ( "ioctl(CDROM_SEND_PACKET)", ARG3,
nethercote73b526f2004-10-31 18:48:21 +00003564 sizeof(struct vki_cdrom_generic_command));
nethercote671398c2004-02-22 18:08:04 +00003565 break;
nethercote73b526f2004-10-31 18:48:21 +00003566 case VKI_CDROMSUBCHNL:
nethercote11e07d32004-11-06 16:17:52 +00003567 PRE_MEM_READ( "ioctl(CDROMSUBCHNL (cdsc_format, char))",
njn22cfccb2004-11-27 16:10:23 +00003568 (Addr) &(((struct vki_cdrom_subchnl*) ARG3)->cdsc_format),
3569 sizeof(((struct vki_cdrom_subchnl*) ARG3)->cdsc_format));
3570 PRE_MEM_WRITE( "ioctl(CDROMSUBCHNL)", ARG3,
nethercote73b526f2004-10-31 18:48:21 +00003571 sizeof(struct vki_cdrom_subchnl));
jsgf855d93d2003-10-13 22:26:55 +00003572 break;
nethercote73b526f2004-10-31 18:48:21 +00003573 case VKI_CDROMREADMODE2:
njn22cfccb2004-11-27 16:10:23 +00003574 PRE_MEM_READ( "ioctl(CDROMREADMODE2)", ARG3, VKI_CD_FRAMESIZE_RAW0 );
nethercote671398c2004-02-22 18:08:04 +00003575 break;
nethercote73b526f2004-10-31 18:48:21 +00003576 case VKI_CDROMREADTOCHDR:
njn22cfccb2004-11-27 16:10:23 +00003577 PRE_MEM_WRITE( "ioctl(CDROMREADTOCHDR)", ARG3,
nethercote73b526f2004-10-31 18:48:21 +00003578 sizeof(struct vki_cdrom_tochdr));
jsgf855d93d2003-10-13 22:26:55 +00003579 break;
nethercote73b526f2004-10-31 18:48:21 +00003580 case VKI_CDROMREADTOCENTRY:
nethercote11e07d32004-11-06 16:17:52 +00003581 PRE_MEM_READ( "ioctl(CDROMREADTOCENTRY (cdte_format, char))",
njn22cfccb2004-11-27 16:10:23 +00003582 (Addr) &(((struct vki_cdrom_tocentry*) ARG3)->cdte_format),
3583 sizeof(((struct vki_cdrom_tocentry*) ARG3)->cdte_format));
nethercote11e07d32004-11-06 16:17:52 +00003584 PRE_MEM_READ( "ioctl(CDROMREADTOCENTRY (cdte_track, char))",
njn22cfccb2004-11-27 16:10:23 +00003585 (Addr) &(((struct vki_cdrom_tocentry*) ARG3)->cdte_track),
3586 sizeof(((struct vki_cdrom_tocentry*) ARG3)->cdte_track));
3587 PRE_MEM_WRITE( "ioctl(CDROMREADTOCENTRY)", ARG3,
nethercote73b526f2004-10-31 18:48:21 +00003588 sizeof(struct vki_cdrom_tocentry));
jsgf855d93d2003-10-13 22:26:55 +00003589 break;
nethercote73b526f2004-10-31 18:48:21 +00003590 case VKI_CDROMMULTISESSION: /* 0x5310 */
njn22cfccb2004-11-27 16:10:23 +00003591 PRE_MEM_WRITE( "ioctl(CDROMMULTISESSION)", ARG3,
nethercote73b526f2004-10-31 18:48:21 +00003592 sizeof(struct vki_cdrom_multisession));
thughes5b788fb2004-09-11 15:07:14 +00003593 break;
nethercote73b526f2004-10-31 18:48:21 +00003594 case VKI_CDROMVOLREAD: /* 0x5313 */
njn22cfccb2004-11-27 16:10:23 +00003595 PRE_MEM_WRITE( "ioctl(CDROMVOLREAD)", ARG3,
nethercote73b526f2004-10-31 18:48:21 +00003596 sizeof(struct vki_cdrom_volctrl));
thughes5b788fb2004-09-11 15:07:14 +00003597 break;
nethercote73b526f2004-10-31 18:48:21 +00003598 case VKI_CDROMREADAUDIO: /* 0x530e */
njn22cfccb2004-11-27 16:10:23 +00003599 PRE_MEM_READ( "ioctl(CDROMREADAUDIO)", ARG3,
nethercote73b526f2004-10-31 18:48:21 +00003600 sizeof (struct vki_cdrom_read_audio));
njn22cfccb2004-11-27 16:10:23 +00003601 if ( ARG3 ) {
thughes5b788fb2004-09-11 15:07:14 +00003602 /* ToDo: don't do any of the following if the structure is invalid */
njn22cfccb2004-11-27 16:10:23 +00003603 struct vki_cdrom_read_audio *cra = (struct vki_cdrom_read_audio *) ARG3;
nethercoteef0c7662004-11-06 15:38:43 +00003604 PRE_MEM_WRITE( "ioctl(CDROMREADAUDIO).buf",
3605 (Addr)(cra->buf), cra->nframes * VKI_CD_FRAMESIZE_RAW);
thughes5b788fb2004-09-11 15:07:14 +00003606 }
3607 break;
nethercote73b526f2004-10-31 18:48:21 +00003608 case VKI_CDROMPLAYMSF:
njn22cfccb2004-11-27 16:10:23 +00003609 PRE_MEM_READ( "ioctl(CDROMPLAYMSF)", ARG3, sizeof(struct vki_cdrom_msf));
jsgf855d93d2003-10-13 22:26:55 +00003610 break;
3611 /* The following two are probably bogus (should check args
3612 for readability). JRS 20021117 */
nethercote73b526f2004-10-31 18:48:21 +00003613 case VKI_CDROM_DRIVE_STATUS: /* 0x5326 */
3614 case VKI_CDROM_CLEAR_OPTIONS: /* 0x5321 */
jsgf855d93d2003-10-13 22:26:55 +00003615 break;
thughes66d80092004-06-19 12:41:05 +00003616
nethercote73b526f2004-10-31 18:48:21 +00003617 case VKI_FIGETBSZ:
njn22cfccb2004-11-27 16:10:23 +00003618 PRE_MEM_WRITE( "ioctl(FIGETBSZ)", ARG3, sizeof(unsigned long));
thughes66d80092004-06-19 12:41:05 +00003619 break;
nethercote73b526f2004-10-31 18:48:21 +00003620 case VKI_FIBMAP:
njn22cfccb2004-11-27 16:10:23 +00003621 PRE_MEM_READ( "ioctl(FIBMAP)", ARG3, sizeof(unsigned long));
thughes66d80092004-06-19 12:41:05 +00003622 break;
3623
nethercote73b526f2004-10-31 18:48:21 +00003624 case VKI_FBIOGET_VSCREENINFO: /* 0x4600 */
njn22cfccb2004-11-27 16:10:23 +00003625 PRE_MEM_WRITE( "ioctl(FBIOGET_VSCREENINFO)", ARG3,
nethercote73b526f2004-10-31 18:48:21 +00003626 sizeof(struct vki_fb_var_screeninfo));
thughes44e35582004-04-21 15:52:33 +00003627 break;
nethercote73b526f2004-10-31 18:48:21 +00003628 case VKI_FBIOGET_FSCREENINFO: /* 0x4602 */
njn22cfccb2004-11-27 16:10:23 +00003629 PRE_MEM_WRITE( "ioctl(FBIOGET_FSCREENINFO)", ARG3,
nethercote73b526f2004-10-31 18:48:21 +00003630 sizeof(struct vki_fb_fix_screeninfo));
thughes44e35582004-04-21 15:52:33 +00003631 break;
jsgf855d93d2003-10-13 22:26:55 +00003632
nethercote73b526f2004-10-31 18:48:21 +00003633 case VKI_PPCLAIM:
3634 case VKI_PPEXCL:
3635 case VKI_PPYIELD:
3636 case VKI_PPRELEASE:
thughesd9895482004-08-16 19:46:55 +00003637 break;
nethercote73b526f2004-10-31 18:48:21 +00003638 case VKI_PPSETMODE:
njn22cfccb2004-11-27 16:10:23 +00003639 PRE_MEM_READ( "ioctl(PPSETMODE)", ARG3, sizeof(int) );
thughesd9895482004-08-16 19:46:55 +00003640 break;
nethercote73b526f2004-10-31 18:48:21 +00003641 case VKI_PPGETMODE:
njn22cfccb2004-11-27 16:10:23 +00003642 PRE_MEM_WRITE( "ioctl(PPGETMODE)", ARG3, sizeof(int) );
thughesd9895482004-08-16 19:46:55 +00003643 break;
nethercote73b526f2004-10-31 18:48:21 +00003644 case VKI_PPSETPHASE:
njn22cfccb2004-11-27 16:10:23 +00003645 PRE_MEM_READ( "ioctl(PPSETPHASE)", ARG3, sizeof(int) );
thughesd9895482004-08-16 19:46:55 +00003646 break;
nethercote73b526f2004-10-31 18:48:21 +00003647 case VKI_PPGETPHASE:
njn22cfccb2004-11-27 16:10:23 +00003648 PRE_MEM_WRITE( "ioctl(PPGETPHASE)", ARG3, sizeof(int) );
thughesd9895482004-08-16 19:46:55 +00003649 break;
nethercote73b526f2004-10-31 18:48:21 +00003650 case VKI_PPGETMODES:
njn22cfccb2004-11-27 16:10:23 +00003651 PRE_MEM_WRITE( "ioctl(PPGETMODES)", ARG3, sizeof(unsigned int) );
thughesd9895482004-08-16 19:46:55 +00003652 break;
nethercote73b526f2004-10-31 18:48:21 +00003653 case VKI_PPSETFLAGS:
njn22cfccb2004-11-27 16:10:23 +00003654 PRE_MEM_READ( "ioctl(PPSETFLAGS)", ARG3, sizeof(int) );
thughesd9895482004-08-16 19:46:55 +00003655 break;
nethercote73b526f2004-10-31 18:48:21 +00003656 case VKI_PPGETFLAGS:
njn22cfccb2004-11-27 16:10:23 +00003657 PRE_MEM_WRITE( "ioctl(PPGETFLAGS)", ARG3, sizeof(int) );
thughesd9895482004-08-16 19:46:55 +00003658 break;
nethercote73b526f2004-10-31 18:48:21 +00003659 case VKI_PPRSTATUS:
njn22cfccb2004-11-27 16:10:23 +00003660 PRE_MEM_WRITE( "ioctl(PPRSTATUS)", ARG3, sizeof(unsigned char) );
thughesd9895482004-08-16 19:46:55 +00003661 break;
nethercote73b526f2004-10-31 18:48:21 +00003662 case VKI_PPRDATA:
njn22cfccb2004-11-27 16:10:23 +00003663 PRE_MEM_WRITE( "ioctl(PPRDATA)", ARG3, sizeof(unsigned char) );
thughesd9895482004-08-16 19:46:55 +00003664 break;
nethercote73b526f2004-10-31 18:48:21 +00003665 case VKI_PPRCONTROL:
njn22cfccb2004-11-27 16:10:23 +00003666 PRE_MEM_WRITE( "ioctl(PPRCONTROL)", ARG3, sizeof(unsigned char) );
thughesd9895482004-08-16 19:46:55 +00003667 break;
nethercote73b526f2004-10-31 18:48:21 +00003668 case VKI_PPWDATA:
njn22cfccb2004-11-27 16:10:23 +00003669 PRE_MEM_READ( "ioctl(PPWDATA)", ARG3, sizeof(unsigned char) );
thughesd9895482004-08-16 19:46:55 +00003670 break;
nethercote73b526f2004-10-31 18:48:21 +00003671 case VKI_PPWCONTROL:
njn22cfccb2004-11-27 16:10:23 +00003672 PRE_MEM_READ( "ioctl(PPWCONTROL)", ARG3, sizeof(unsigned char) );
thughesd9895482004-08-16 19:46:55 +00003673 break;
nethercote73b526f2004-10-31 18:48:21 +00003674 case VKI_PPFCONTROL:
njn22cfccb2004-11-27 16:10:23 +00003675 PRE_MEM_READ( "ioctl(PPFCONTROL)", ARG3, 2 * sizeof(unsigned char) );
thughesd9895482004-08-16 19:46:55 +00003676 break;
nethercote73b526f2004-10-31 18:48:21 +00003677 case VKI_PPDATADIR:
njn22cfccb2004-11-27 16:10:23 +00003678 PRE_MEM_READ( "ioctl(PPDATADIR)", ARG3, sizeof(int) );
thughesd9895482004-08-16 19:46:55 +00003679 break;
nethercote73b526f2004-10-31 18:48:21 +00003680 case VKI_PPNEGOT:
njn22cfccb2004-11-27 16:10:23 +00003681 PRE_MEM_READ( "ioctl(PPNEGOT)", ARG3, sizeof(int) );
thughesd9895482004-08-16 19:46:55 +00003682 break;
nethercote73b526f2004-10-31 18:48:21 +00003683 case VKI_PPWCTLONIRQ:
njn22cfccb2004-11-27 16:10:23 +00003684 PRE_MEM_READ( "ioctl(PPWCTLONIRQ)",ARG3, sizeof(unsigned char) );
thughesd9895482004-08-16 19:46:55 +00003685 break;
nethercote73b526f2004-10-31 18:48:21 +00003686 case VKI_PPCLRIRQ:
njn22cfccb2004-11-27 16:10:23 +00003687 PRE_MEM_WRITE( "ioctl(PPCLRIRQ)", ARG3, sizeof(int) );
thughesd9895482004-08-16 19:46:55 +00003688 break;
nethercote73b526f2004-10-31 18:48:21 +00003689 case VKI_PPSETTIME:
njn22cfccb2004-11-27 16:10:23 +00003690 PRE_MEM_READ( "ioctl(PPSETTIME)", ARG3, sizeof(struct vki_timeval) );
thughesd9895482004-08-16 19:46:55 +00003691 break;
nethercote73b526f2004-10-31 18:48:21 +00003692 case VKI_PPGETTIME:
njn22cfccb2004-11-27 16:10:23 +00003693 PRE_MEM_WRITE( "ioctl(PPGETTIME)", ARG3, sizeof(struct vki_timeval) );
thughesd9895482004-08-16 19:46:55 +00003694 break;
3695
thughesb3d3bcf2004-11-13 00:36:15 +00003696 case VKI_GIO_FONT:
njn22cfccb2004-11-27 16:10:23 +00003697 PRE_MEM_WRITE( "ioctl(GIO_FONT)", ARG3, 32 * 256 );
thughesb3d3bcf2004-11-13 00:36:15 +00003698 break;
3699 case VKI_PIO_FONT:
njn22cfccb2004-11-27 16:10:23 +00003700 PRE_MEM_READ( "ioctl(PIO_FONT)", ARG3, 32 * 256 );
thughesb3d3bcf2004-11-13 00:36:15 +00003701 break;
3702
3703 case VKI_GIO_FONTX:
njn22cfccb2004-11-27 16:10:23 +00003704 PRE_MEM_READ( "ioctl(GIO_FONTX)", ARG3, sizeof(struct vki_consolefontdesc) );
3705 if ( ARG3 ) {
thughesb3d3bcf2004-11-13 00:36:15 +00003706 /* ToDo: don't do any of the following if the structure is invalid */
njn22cfccb2004-11-27 16:10:23 +00003707 struct vki_consolefontdesc *cfd = (struct vki_consolefontdesc *)ARG3;
thughesb3d3bcf2004-11-13 00:36:15 +00003708 PRE_MEM_WRITE( "ioctl(GIO_FONTX).chardata", (Addr)cfd->chardata,
3709 32 * cfd->charcount );
3710 }
3711 break;
3712 case VKI_PIO_FONTX:
njn22cfccb2004-11-27 16:10:23 +00003713 PRE_MEM_READ( "ioctl(PIO_FONTX)", ARG3, sizeof(struct vki_consolefontdesc) );
3714 if ( ARG3 ) {
thughesb3d3bcf2004-11-13 00:36:15 +00003715 /* ToDo: don't do any of the following if the structure is invalid */
njn22cfccb2004-11-27 16:10:23 +00003716 struct vki_consolefontdesc *cfd = (struct vki_consolefontdesc *)ARG3;
thughesb3d3bcf2004-11-13 00:36:15 +00003717 PRE_MEM_READ( "ioctl(PIO_FONTX).chardata", (Addr)cfd->chardata,
3718 32 * cfd->charcount );
3719 }
3720 break;
3721
3722 case VKI_PIO_FONTRESET:
3723 break;
3724
3725 case VKI_GIO_CMAP:
njn22cfccb2004-11-27 16:10:23 +00003726 PRE_MEM_WRITE( "ioctl(GIO_CMAP)", ARG3, 16 * 3 );
thughesb3d3bcf2004-11-13 00:36:15 +00003727 break;
3728 case VKI_PIO_CMAP:
njn22cfccb2004-11-27 16:10:23 +00003729 PRE_MEM_READ( "ioctl(PIO_CMAP)", ARG3, 16 * 3 );
thughesb3d3bcf2004-11-13 00:36:15 +00003730 break;
3731
3732 case VKI_KIOCSOUND:
3733 case VKI_KDMKTONE:
3734 break;
3735
3736 case VKI_KDGETLED:
njn22cfccb2004-11-27 16:10:23 +00003737 PRE_MEM_WRITE( "ioctl(KDGETLED)", ARG3, sizeof(char) );
thughesb3d3bcf2004-11-13 00:36:15 +00003738 break;
3739 case VKI_KDSETLED:
3740 break;
3741
3742 case VKI_KDGKBTYPE:
njn22cfccb2004-11-27 16:10:23 +00003743 PRE_MEM_WRITE( "ioctl(KDGKBTYPE)", ARG3, sizeof(char) );
thughesb3d3bcf2004-11-13 00:36:15 +00003744 break;
3745
3746 case VKI_KDADDIO:
3747 case VKI_KDDELIO:
3748 case VKI_KDENABIO:
3749 case VKI_KDDISABIO:
3750 break;
3751
3752 case VKI_KDSETMODE:
3753 break;
3754 case VKI_KDGETMODE:
njn22cfccb2004-11-27 16:10:23 +00003755 PRE_MEM_WRITE( "ioctl(KDGETMODE)", ARG3, sizeof(int) );
thughesb3d3bcf2004-11-13 00:36:15 +00003756 break;
3757
3758 case VKI_KDMAPDISP:
3759 case VKI_KDUNMAPDISP:
3760 break;
3761
3762 case VKI_GIO_SCRNMAP:
njn22cfccb2004-11-27 16:10:23 +00003763 PRE_MEM_WRITE( "ioctl(GIO_SCRNMAP)", ARG3, VKI_E_TABSZ );
thughesb3d3bcf2004-11-13 00:36:15 +00003764 break;
3765 case VKI_PIO_SCRNMAP:
njn22cfccb2004-11-27 16:10:23 +00003766 PRE_MEM_READ( "ioctl(PIO_SCRNMAP)", ARG3, VKI_E_TABSZ );
thughesb3d3bcf2004-11-13 00:36:15 +00003767 break;
3768 case VKI_GIO_UNISCRNMAP:
njn22cfccb2004-11-27 16:10:23 +00003769 PRE_MEM_WRITE( "ioctl(GIO_UNISCRNMAP)", ARG3,
thughesb3d3bcf2004-11-13 00:36:15 +00003770 VKI_E_TABSZ * sizeof(unsigned short) );
3771 break;
3772 case VKI_PIO_UNISCRNMAP:
njn22cfccb2004-11-27 16:10:23 +00003773 PRE_MEM_READ( "ioctl(PIO_UNISCRNMAP)", ARG3,
thughesb3d3bcf2004-11-13 00:36:15 +00003774 VKI_E_TABSZ * sizeof(unsigned short) );
3775 break;
3776
3777 case VKI_KDGKBMODE:
njn22cfccb2004-11-27 16:10:23 +00003778 PRE_MEM_WRITE( "ioctl(KDGKBMODE)", ARG3, sizeof(int) );
thughesb3d3bcf2004-11-13 00:36:15 +00003779 break;
3780 case VKI_KDSKBMODE:
3781 break;
3782
3783 case VKI_KDGKBMETA:
njn22cfccb2004-11-27 16:10:23 +00003784 PRE_MEM_WRITE( "ioctl(KDGKBMETA)", ARG3, sizeof(int) );
thughesb3d3bcf2004-11-13 00:36:15 +00003785 break;
3786 case VKI_KDSKBMETA:
3787 break;
3788
3789 case VKI_KDGKBLED:
njn22cfccb2004-11-27 16:10:23 +00003790 PRE_MEM_WRITE( "ioctl(KDGKBLED)", ARG3, sizeof(char) );
thughesb3d3bcf2004-11-13 00:36:15 +00003791 break;
3792 case VKI_KDSKBLED:
3793 break;
3794
3795 case VKI_KDGKBENT:
3796 PRE_MEM_READ( "ioctl(KDGKBENT).kb_table",
njn22cfccb2004-11-27 16:10:23 +00003797 (Addr)&((struct vki_kbentry *)ARG3)->kb_table,
3798 sizeof(((struct vki_kbentry *)ARG3)->kb_table) );
thughesb3d3bcf2004-11-13 00:36:15 +00003799 PRE_MEM_READ( "ioctl(KDGKBENT).kb_index",
njn22cfccb2004-11-27 16:10:23 +00003800 (Addr)&((struct vki_kbentry *)ARG3)->kb_index,
3801 sizeof(((struct vki_kbentry *)ARG3)->kb_index) );
thughesb3d3bcf2004-11-13 00:36:15 +00003802 PRE_MEM_WRITE( "ioctl(KDGKBENT).kb_value",
njn22cfccb2004-11-27 16:10:23 +00003803 (Addr)&((struct vki_kbentry *)ARG3)->kb_value,
3804 sizeof(((struct vki_kbentry *)ARG3)->kb_value) );
thughesb3d3bcf2004-11-13 00:36:15 +00003805 break;
3806 case VKI_KDSKBENT:
3807 PRE_MEM_READ( "ioctl(KDSKBENT).kb_table",
njn22cfccb2004-11-27 16:10:23 +00003808 (Addr)&((struct vki_kbentry *)ARG3)->kb_table,
3809 sizeof(((struct vki_kbentry *)ARG3)->kb_table) );
thughesb3d3bcf2004-11-13 00:36:15 +00003810 PRE_MEM_READ( "ioctl(KDSKBENT).kb_index",
njn22cfccb2004-11-27 16:10:23 +00003811 (Addr)&((struct vki_kbentry *)ARG3)->kb_index,
3812 sizeof(((struct vki_kbentry *)ARG3)->kb_index) );
thughesb3d3bcf2004-11-13 00:36:15 +00003813 PRE_MEM_READ( "ioctl(KDSKBENT).kb_value",
njn22cfccb2004-11-27 16:10:23 +00003814 (Addr)&((struct vki_kbentry *)ARG3)->kb_value,
3815 sizeof(((struct vki_kbentry *)ARG3)->kb_value) );
thughesb3d3bcf2004-11-13 00:36:15 +00003816 break;
3817
3818 case VKI_KDGKBSENT:
3819 PRE_MEM_READ( "ioctl(KDGKBSENT).kb_func",
njn22cfccb2004-11-27 16:10:23 +00003820 (Addr)&((struct vki_kbsentry *)ARG3)->kb_func,
3821 sizeof(((struct vki_kbsentry *)ARG3)->kb_func) );
thughesb3d3bcf2004-11-13 00:36:15 +00003822 PRE_MEM_WRITE( "ioctl(KDGKSENT).kb_string",
njn22cfccb2004-11-27 16:10:23 +00003823 (Addr)((struct vki_kbsentry *)ARG3)->kb_string,
3824 sizeof(((struct vki_kbsentry *)ARG3)->kb_string) );
thughesb3d3bcf2004-11-13 00:36:15 +00003825 break;
3826 case VKI_KDSKBSENT:
3827 PRE_MEM_READ( "ioctl(KDSKBSENT).kb_func",
njn22cfccb2004-11-27 16:10:23 +00003828 (Addr)&((struct vki_kbsentry *)ARG3)->kb_func,
3829 sizeof(((struct vki_kbsentry *)ARG3)->kb_func) );
thughesb3d3bcf2004-11-13 00:36:15 +00003830 PRE_MEM_RASCIIZ( "ioctl(KDSKBSENT).kb_string",
njn22cfccb2004-11-27 16:10:23 +00003831 (Addr)((struct vki_kbsentry *)ARG3)->kb_string );
thughesb3d3bcf2004-11-13 00:36:15 +00003832 break;
3833
3834 case VKI_KDGKBDIACR:
njn22cfccb2004-11-27 16:10:23 +00003835 PRE_MEM_WRITE( "ioctl(KDGKBDIACR)", ARG3, sizeof(struct vki_kbdiacrs) );
thughesb3d3bcf2004-11-13 00:36:15 +00003836 break;
3837 case VKI_KDSKBDIACR:
njn22cfccb2004-11-27 16:10:23 +00003838 PRE_MEM_READ( "ioctl(KDSKBDIACR)", ARG3, sizeof(struct vki_kbdiacrs) );
thughesb3d3bcf2004-11-13 00:36:15 +00003839 break;
3840
3841 case VKI_KDGETKEYCODE:
3842 PRE_MEM_READ( "ioctl(KDGETKEYCODE).scancode",
njn22cfccb2004-11-27 16:10:23 +00003843 (Addr)&((struct vki_kbkeycode *)ARG3)->scancode,
3844 sizeof(((struct vki_kbkeycode *)ARG3)->scancode) );
thughesb3d3bcf2004-11-13 00:36:15 +00003845 PRE_MEM_WRITE( "ioctl(KDGETKEYCODE).keycode",
njn22cfccb2004-11-27 16:10:23 +00003846 (Addr)((struct vki_kbkeycode *)ARG3)->keycode,
3847 sizeof(((struct vki_kbkeycode *)ARG3)->keycode) );
thughesb3d3bcf2004-11-13 00:36:15 +00003848 break;
3849 case VKI_KDSETKEYCODE:
3850 PRE_MEM_READ( "ioctl(KDSETKEYCODE).scancode",
njn22cfccb2004-11-27 16:10:23 +00003851 (Addr)&((struct vki_kbkeycode *)ARG3)->scancode,
3852 sizeof(((struct vki_kbkeycode *)ARG3)->scancode) );
thughesb3d3bcf2004-11-13 00:36:15 +00003853 PRE_MEM_READ( "ioctl(KDSETKEYCODE).keycode",
njn22cfccb2004-11-27 16:10:23 +00003854 (Addr)((struct vki_kbkeycode *)ARG3)->keycode,
3855 sizeof(((struct vki_kbkeycode *)ARG3)->keycode) );
thughesb3d3bcf2004-11-13 00:36:15 +00003856 break;
3857
3858 case VKI_KDSIGACCEPT:
3859 break;
3860
3861 case VKI_KDKBDREP:
njn22cfccb2004-11-27 16:10:23 +00003862 PRE_MEM_READ( "ioctl(KBKBDREP)", ARG3, sizeof(struct vki_kbd_repeat) );
thughesb3d3bcf2004-11-13 00:36:15 +00003863 break;
3864
jsgf855d93d2003-10-13 22:26:55 +00003865 /* We don't have any specific information on it, so
3866 try to do something reasonable based on direction and
3867 size bits. The encoding scheme is described in
3868 /usr/include/asm/ioctl.h.
3869
3870 According to Simon Hausmann, _IOC_READ means the kernel
3871 writes a value to the ioctl value passed from the user
3872 space and the other way around with _IOC_WRITE. */
3873 default: {
njn22cfccb2004-11-27 16:10:23 +00003874 UInt dir = _VKI_IOC_DIR(ARG2);
3875 UInt size = _VKI_IOC_SIZE(ARG2);
njn628add62005-11-12 18:21:40 +00003876 if (VG_(strstr)(VG_(clo_sim_hints), "lax-ioctls") != NULL) {
jsgf855d93d2003-10-13 22:26:55 +00003877 /*
3878 * Be very lax about ioctl handling; the only
3879 * assumption is that the size is correct. Doesn't
3880 * require the full buffer to be initialized when
3881 * writing. Without this, using some device
3882 * drivers with a large number of strange ioctl
3883 * commands becomes very tiresome.
3884 */
nethercote73b526f2004-10-31 18:48:21 +00003885 } else if (/* size == 0 || */ dir == _VKI_IOC_NONE) {
jsgf855d93d2003-10-13 22:26:55 +00003886 static Int moans = 3;
sewardj1fa7d2c2005-06-13 18:22:17 +00003887 if (moans > 0 && !VG_(clo_xml)) {
jsgf855d93d2003-10-13 22:26:55 +00003888 moans--;
3889 VG_(message)(Vg_UserMsg,
3890 "Warning: noted but unhandled ioctl 0x%x"
3891 " with no size/direction hints",
njn22cfccb2004-11-27 16:10:23 +00003892 ARG2);
jsgf855d93d2003-10-13 22:26:55 +00003893 VG_(message)(Vg_UserMsg,
3894 " This could cause spurious value errors"
3895 " to appear.");
3896 VG_(message)(Vg_UserMsg,
3897 " See README_MISSING_SYSCALL_OR_IOCTL for "
3898 "guidance on writing a proper wrapper." );
3899 }
3900 } else {
nethercote73b526f2004-10-31 18:48:21 +00003901 if ((dir & _VKI_IOC_WRITE) && size > 0)
njn22cfccb2004-11-27 16:10:23 +00003902 PRE_MEM_READ( "ioctl(generic)", ARG3, size);
nethercote73b526f2004-10-31 18:48:21 +00003903 if ((dir & _VKI_IOC_READ) && size > 0)
njn22cfccb2004-11-27 16:10:23 +00003904 PRE_MEM_WRITE( "ioctl(generic)", ARG3, size);
jsgf855d93d2003-10-13 22:26:55 +00003905 }
3906 break;
3907 }
3908 }
3909}
3910
nethercote85a456f2004-11-16 17:31:56 +00003911POST(sys_ioctl)
jsgf855d93d2003-10-13 22:26:55 +00003912{
sewardja8d8e232005-06-07 20:04:56 +00003913 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00003914 switch (ARG2 /* request */) {
nethercote73b526f2004-10-31 18:48:21 +00003915 case VKI_TCSETS:
3916 case VKI_TCSETSW:
3917 case VKI_TCSETSF:
jsgf855d93d2003-10-13 22:26:55 +00003918 break;
nethercote73b526f2004-10-31 18:48:21 +00003919 case VKI_TCGETS:
njn22cfccb2004-11-27 16:10:23 +00003920 POST_MEM_WRITE( ARG3, sizeof(struct vki_termios) );
jsgf855d93d2003-10-13 22:26:55 +00003921 break;
nethercote73b526f2004-10-31 18:48:21 +00003922 case VKI_TCSETA:
3923 case VKI_TCSETAW:
3924 case VKI_TCSETAF:
jsgf855d93d2003-10-13 22:26:55 +00003925 break;
nethercote73b526f2004-10-31 18:48:21 +00003926 case VKI_TCGETA:
njn22cfccb2004-11-27 16:10:23 +00003927 POST_MEM_WRITE( ARG3, sizeof(struct vki_termio) );
jsgf855d93d2003-10-13 22:26:55 +00003928 break;
nethercote73b526f2004-10-31 18:48:21 +00003929 case VKI_TCSBRK:
3930 case VKI_TCXONC:
3931 case VKI_TCSBRKP:
3932 case VKI_TCFLSH:
jsgf855d93d2003-10-13 22:26:55 +00003933 break;
nethercote73b526f2004-10-31 18:48:21 +00003934 case VKI_TIOCGWINSZ:
njn22cfccb2004-11-27 16:10:23 +00003935 POST_MEM_WRITE( ARG3, sizeof(struct vki_winsize) );
jsgf855d93d2003-10-13 22:26:55 +00003936 break;
nethercote73b526f2004-10-31 18:48:21 +00003937 case VKI_TIOCSWINSZ:
3938 case VKI_TIOCMBIS:
3939 case VKI_TIOCMBIC:
3940 case VKI_TIOCMSET:
jsgf855d93d2003-10-13 22:26:55 +00003941 break;
tom62ba7582005-07-28 16:26:34 +00003942 case VKI_TIOCMGET:
3943 POST_MEM_WRITE( ARG3, sizeof(unsigned int) );
3944 break;
nethercote73b526f2004-10-31 18:48:21 +00003945 case VKI_TIOCLINUX:
njn22cfccb2004-11-27 16:10:23 +00003946 POST_MEM_WRITE( ARG3, sizeof(char *) );
jsgf855d93d2003-10-13 22:26:55 +00003947 break;
nethercote73b526f2004-10-31 18:48:21 +00003948 case VKI_TIOCGPGRP:
jsgf855d93d2003-10-13 22:26:55 +00003949 /* Get process group ID for foreground processing group. */
njn22cfccb2004-11-27 16:10:23 +00003950 POST_MEM_WRITE( ARG3, sizeof(vki_pid_t) );
jsgf855d93d2003-10-13 22:26:55 +00003951 break;
nethercote73b526f2004-10-31 18:48:21 +00003952 case VKI_TIOCSPGRP:
jsgf855d93d2003-10-13 22:26:55 +00003953 /* Set a process group ID? */
njn22cfccb2004-11-27 16:10:23 +00003954 POST_MEM_WRITE( ARG3, sizeof(vki_pid_t) );
jsgf855d93d2003-10-13 22:26:55 +00003955 break;
nethercote73b526f2004-10-31 18:48:21 +00003956 case VKI_TIOCGPTN: /* Get Pty Number (of pty-mux device) */
njn22cfccb2004-11-27 16:10:23 +00003957 POST_MEM_WRITE( ARG3, sizeof(int));
jsgf855d93d2003-10-13 22:26:55 +00003958 break;
nethercote73b526f2004-10-31 18:48:21 +00003959 case VKI_TIOCSCTTY:
jsgf855d93d2003-10-13 22:26:55 +00003960 break;
nethercote73b526f2004-10-31 18:48:21 +00003961 case VKI_TIOCSPTLCK: /* Lock/unlock Pty */
jsgf855d93d2003-10-13 22:26:55 +00003962 break;
nethercote73b526f2004-10-31 18:48:21 +00003963 case VKI_FIONBIO:
jsgf855d93d2003-10-13 22:26:55 +00003964 break;
nethercote73b526f2004-10-31 18:48:21 +00003965 case VKI_FIOASYNC:
jsgf855d93d2003-10-13 22:26:55 +00003966 break;
nethercote73b526f2004-10-31 18:48:21 +00003967 case VKI_FIONREAD: /* identical to SIOCINQ */
njn22cfccb2004-11-27 16:10:23 +00003968 POST_MEM_WRITE( ARG3, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00003969 break;
3970
nethercote73b526f2004-10-31 18:48:21 +00003971 case VKI_SG_SET_COMMAND_Q:
jsgf855d93d2003-10-13 22:26:55 +00003972 break;
nethercote73b526f2004-10-31 18:48:21 +00003973 case VKI_SG_IO:
njn22cfccb2004-11-27 16:10:23 +00003974 POST_MEM_WRITE(ARG3, sizeof(vki_sg_io_hdr_t));
jsgf855d93d2003-10-13 22:26:55 +00003975 break;
nethercote73b526f2004-10-31 18:48:21 +00003976 case VKI_SG_GET_SCSI_ID:
njn22cfccb2004-11-27 16:10:23 +00003977 POST_MEM_WRITE(ARG3, sizeof(vki_sg_scsi_id_t));
jsgf855d93d2003-10-13 22:26:55 +00003978 break;
nethercote73b526f2004-10-31 18:48:21 +00003979 case VKI_SG_SET_RESERVED_SIZE:
jsgf855d93d2003-10-13 22:26:55 +00003980 break;
nethercote73b526f2004-10-31 18:48:21 +00003981 case VKI_SG_SET_TIMEOUT:
jsgf855d93d2003-10-13 22:26:55 +00003982 break;
nethercote73b526f2004-10-31 18:48:21 +00003983 case VKI_SG_GET_RESERVED_SIZE:
njn22cfccb2004-11-27 16:10:23 +00003984 POST_MEM_WRITE(ARG3, sizeof(int));
jsgf855d93d2003-10-13 22:26:55 +00003985 break;
nethercote73b526f2004-10-31 18:48:21 +00003986 case VKI_SG_GET_TIMEOUT:
njn22cfccb2004-11-27 16:10:23 +00003987 POST_MEM_WRITE(ARG3, sizeof(int));
jsgf855d93d2003-10-13 22:26:55 +00003988 break;
nethercote73b526f2004-10-31 18:48:21 +00003989 case VKI_SG_GET_VERSION_NUM:
jsgf855d93d2003-10-13 22:26:55 +00003990 break;
nethercote73b526f2004-10-31 18:48:21 +00003991 case VKI_SG_EMULATED_HOST:
njn22cfccb2004-11-27 16:10:23 +00003992 POST_MEM_WRITE(ARG3, sizeof(int));
thughes5b788fb2004-09-11 15:07:14 +00003993 break;
nethercote73b526f2004-10-31 18:48:21 +00003994 case VKI_SG_GET_SG_TABLESIZE:
njn22cfccb2004-11-27 16:10:23 +00003995 POST_MEM_WRITE(ARG3, sizeof(int));
thughes5b788fb2004-09-11 15:07:14 +00003996 break;
jsgf855d93d2003-10-13 22:26:55 +00003997
muellera4b153a2003-11-19 22:07:14 +00003998 case VKI_IIOCGETCPS:
njn22cfccb2004-11-27 16:10:23 +00003999 POST_MEM_WRITE( ARG3, VKI_ISDN_MAX_CHANNELS * 2 * sizeof(unsigned long) );
jsgf855d93d2003-10-13 22:26:55 +00004000 break;
muellera4b153a2003-11-19 22:07:14 +00004001 case VKI_IIOCNETGPN:
njn22cfccb2004-11-27 16:10:23 +00004002 POST_MEM_WRITE( ARG3, sizeof(vki_isdn_net_ioctl_phone) );
jsgf855d93d2003-10-13 22:26:55 +00004003 break;
4004
4005 /* These all use struct ifreq AFAIK */
nethercote73b526f2004-10-31 18:48:21 +00004006 case VKI_SIOCGIFINDEX: /* get iface index */
njn22cfccb2004-11-27 16:10:23 +00004007 POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_ifindex,
4008 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_ifindex) );
thughesbe811712004-06-17 23:04:58 +00004009 break;
nethercote73b526f2004-10-31 18:48:21 +00004010 case VKI_SIOCGIFFLAGS: /* get flags */
njn22cfccb2004-11-27 16:10:23 +00004011 POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_flags,
4012 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_flags) );
thughesbe811712004-06-17 23:04:58 +00004013 break;
nethercote73b526f2004-10-31 18:48:21 +00004014 case VKI_SIOCGIFHWADDR: /* Get hardware address */
njn22cfccb2004-11-27 16:10:23 +00004015 POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->ifr_hwaddr,
4016 sizeof(((struct vki_ifreq *)ARG3)->ifr_hwaddr) );
thughesbe811712004-06-17 23:04:58 +00004017 break;
nethercote73b526f2004-10-31 18:48:21 +00004018 case VKI_SIOCGIFMTU: /* get MTU size */
njn22cfccb2004-11-27 16:10:23 +00004019 POST_MEM_WRITE( (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_mtu,
4020 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_mtu) );
thughesbe811712004-06-17 23:04:58 +00004021 break;
nethercote73b526f2004-10-31 18:48:21 +00004022 case VKI_SIOCGIFADDR: /* get PA address */
4023 case VKI_SIOCGIFDSTADDR: /* get remote PA address */
4024 case VKI_SIOCGIFBRDADDR: /* get broadcast PA address */
4025 case VKI_SIOCGIFNETMASK: /* get network PA mask */
njncf45fd42004-11-24 16:30:22 +00004026 POST_MEM_WRITE(
njn22cfccb2004-11-27 16:10:23 +00004027 (Addr)&((struct vki_ifreq *)ARG3)->ifr_addr,
4028 sizeof(((struct vki_ifreq *)ARG3)->ifr_addr) );
thughesbe811712004-06-17 23:04:58 +00004029 break;
nethercote73b526f2004-10-31 18:48:21 +00004030 case VKI_SIOCGIFMETRIC: /* get metric */
njncf45fd42004-11-24 16:30:22 +00004031 POST_MEM_WRITE(
njn22cfccb2004-11-27 16:10:23 +00004032 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_metric,
4033 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_metric) );
thughesbe811712004-06-17 23:04:58 +00004034 break;
nethercote73b526f2004-10-31 18:48:21 +00004035 case VKI_SIOCGIFMAP: /* Get device parameters */
njncf45fd42004-11-24 16:30:22 +00004036 POST_MEM_WRITE(
njn22cfccb2004-11-27 16:10:23 +00004037 (Addr)&((struct vki_ifreq *)ARG3)->ifr_map,
4038 sizeof(((struct vki_ifreq *)ARG3)->ifr_map) );
thughesbe811712004-06-17 23:04:58 +00004039 break;
4040 break;
nethercote73b526f2004-10-31 18:48:21 +00004041 case VKI_SIOCGIFTXQLEN: /* Get the tx queue length */
njncf45fd42004-11-24 16:30:22 +00004042 POST_MEM_WRITE(
njn22cfccb2004-11-27 16:10:23 +00004043 (Addr)&((struct vki_ifreq *)ARG3)->ifr_qlen,
4044 sizeof(((struct vki_ifreq *)ARG3)->ifr_qlen) );
thughesbe811712004-06-17 23:04:58 +00004045 break;
nethercote73b526f2004-10-31 18:48:21 +00004046 case VKI_SIOCGIFNAME: /* get iface name */
njncf45fd42004-11-24 16:30:22 +00004047 POST_MEM_WRITE(
njn22cfccb2004-11-27 16:10:23 +00004048 (Addr)&((struct vki_ifreq *)ARG3)->vki_ifr_name,
4049 sizeof(((struct vki_ifreq *)ARG3)->vki_ifr_name) );
jsgf855d93d2003-10-13 22:26:55 +00004050 break;
nethercote73b526f2004-10-31 18:48:21 +00004051 case VKI_SIOCGMIIPHY: /* get hardware entry */
njncf45fd42004-11-24 16:30:22 +00004052 POST_MEM_WRITE(
njn22cfccb2004-11-27 16:10:23 +00004053 (Addr)&((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->phy_id,
4054 sizeof(((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->phy_id) );
thughesbe811712004-06-17 23:04:58 +00004055 break;
nethercote73b526f2004-10-31 18:48:21 +00004056 case VKI_SIOCGMIIREG: /* get hardware entry registers */
njncf45fd42004-11-24 16:30:22 +00004057 POST_MEM_WRITE(
njn22cfccb2004-11-27 16:10:23 +00004058 (Addr)&((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->val_out,
4059 sizeof(((struct vki_mii_ioctl_data *)&((struct vki_ifreq *)ARG3)->vki_ifr_data)->val_out) );
thughesbe811712004-06-17 23:04:58 +00004060 break;
nethercote73b526f2004-10-31 18:48:21 +00004061 case VKI_SIOCGIFCONF: /* get iface list */
jsgf855d93d2003-10-13 22:26:55 +00004062 /* WAS:
njn22cfccb2004-11-27 16:10:23 +00004063 PRE_MEM_WRITE("ioctl(SIOCGIFCONF)", ARG3, sizeof(struct ifconf));
4064 KERNEL_DO_SYSCALL(tid,RES);
4065 if (!VG_(is_kerror)(RES) && RES == 0)
4066 POST_MEM_WRITE(ARG3, sizeof(struct ifconf));
jsgf855d93d2003-10-13 22:26:55 +00004067 */
njn22cfccb2004-11-27 16:10:23 +00004068 if (RES == 0 && ARG3 ) {
4069 struct vki_ifconf *ifc = (struct vki_ifconf *) ARG3;
nethercote73b526f2004-10-31 18:48:21 +00004070 if (ifc->vki_ifc_buf != NULL)
nethercoteef0c7662004-11-06 15:38:43 +00004071 POST_MEM_WRITE( (Addr)(ifc->vki_ifc_buf), ifc->ifc_len );
jsgf855d93d2003-10-13 22:26:55 +00004072 }
4073 break;
nethercote73b526f2004-10-31 18:48:21 +00004074 case VKI_SIOCGSTAMP:
njn22cfccb2004-11-27 16:10:23 +00004075 POST_MEM_WRITE( ARG3, sizeof(struct vki_timeval) );
jsgf855d93d2003-10-13 22:26:55 +00004076 break;
4077 /* SIOCOUTQ is an ioctl that, when called on a socket, returns
4078 the number of bytes currently in that socket's send buffer.
4079 It writes this value as an int to the memory location
4080 indicated by the third argument of ioctl(2). */
nethercote73b526f2004-10-31 18:48:21 +00004081 case VKI_SIOCOUTQ:
njn22cfccb2004-11-27 16:10:23 +00004082 POST_MEM_WRITE(ARG3, sizeof(int));
jsgf855d93d2003-10-13 22:26:55 +00004083 break;
nethercote73b526f2004-10-31 18:48:21 +00004084 case VKI_SIOCGRARP: /* get RARP table entry */
4085 case VKI_SIOCGARP: /* get ARP table entry */
njn22cfccb2004-11-27 16:10:23 +00004086 POST_MEM_WRITE(ARG3, sizeof(struct vki_arpreq));
jsgf855d93d2003-10-13 22:26:55 +00004087 break;
4088
nethercote73b526f2004-10-31 18:48:21 +00004089 case VKI_SIOCSIFFLAGS: /* set flags */
4090 case VKI_SIOCSIFMAP: /* Set device parameters */
4091 case VKI_SIOCSIFTXQLEN: /* Set the tx queue length */
4092 case VKI_SIOCSIFDSTADDR: /* set remote PA address */
4093 case VKI_SIOCSIFBRDADDR: /* set broadcast PA address */
4094 case VKI_SIOCSIFNETMASK: /* set network PA mask */
4095 case VKI_SIOCSIFMETRIC: /* set metric */
4096 case VKI_SIOCSIFADDR: /* set PA address */
4097 case VKI_SIOCSIFMTU: /* set MTU size */
4098 case VKI_SIOCSIFHWADDR: /* set hardware address */
4099 case VKI_SIOCSMIIREG: /* set hardware entry registers */
jsgf855d93d2003-10-13 22:26:55 +00004100 break;
4101 /* Routing table calls. */
nethercote73b526f2004-10-31 18:48:21 +00004102 case VKI_SIOCADDRT: /* add routing table entry */
4103 case VKI_SIOCDELRT: /* delete routing table entry */
jsgf855d93d2003-10-13 22:26:55 +00004104 break;
4105
4106 /* RARP cache control calls. */
nethercote73b526f2004-10-31 18:48:21 +00004107 case VKI_SIOCDRARP: /* delete RARP table entry */
4108 case VKI_SIOCSRARP: /* set RARP table entry */
jsgf855d93d2003-10-13 22:26:55 +00004109 /* ARP cache control calls. */
nethercote73b526f2004-10-31 18:48:21 +00004110 case VKI_SIOCSARP: /* set ARP table entry */
4111 case VKI_SIOCDARP: /* delete ARP table entry */
jsgf855d93d2003-10-13 22:26:55 +00004112 break;
4113
nethercote73b526f2004-10-31 18:48:21 +00004114 case VKI_SIOCGPGRP:
njn22cfccb2004-11-27 16:10:23 +00004115 POST_MEM_WRITE(ARG3, sizeof(int));
thughes1174fed2004-09-11 15:33:17 +00004116 break;
nethercote73b526f2004-10-31 18:48:21 +00004117 case VKI_SIOCSPGRP:
jsgf855d93d2003-10-13 22:26:55 +00004118 break;
4119
4120 /* linux/soundcard interface (OSS) */
nethercote73b526f2004-10-31 18:48:21 +00004121 case VKI_SNDCTL_SEQ_GETOUTCOUNT:
4122 case VKI_SNDCTL_SEQ_GETINCOUNT:
4123 case VKI_SNDCTL_SEQ_PERCMODE:
4124 case VKI_SNDCTL_SEQ_TESTMIDI:
4125 case VKI_SNDCTL_SEQ_RESETSAMPLES:
4126 case VKI_SNDCTL_SEQ_NRSYNTHS:
4127 case VKI_SNDCTL_SEQ_NRMIDIS:
4128 case VKI_SNDCTL_SEQ_GETTIME:
4129 case VKI_SNDCTL_DSP_GETFMTS:
4130 case VKI_SNDCTL_DSP_GETTRIGGER:
4131 case VKI_SNDCTL_DSP_GETODELAY:
4132 case VKI_SNDCTL_DSP_GETSPDIF:
4133 case VKI_SNDCTL_DSP_GETCAPS:
4134 case VKI_SOUND_PCM_READ_RATE:
4135 case VKI_SOUND_PCM_READ_CHANNELS:
4136 case VKI_SOUND_PCM_READ_BITS:
cerion85665ca2005-06-20 15:51:07 +00004137#if !defined(VGA_ppc32)
nethercote73b526f2004-10-31 18:48:21 +00004138 case (VKI_SOUND_PCM_READ_BITS|0x40000000): /* what the fuck ? */
cerion85665ca2005-06-20 15:51:07 +00004139#endif
nethercote73b526f2004-10-31 18:48:21 +00004140 case VKI_SOUND_PCM_READ_FILTER:
njn22cfccb2004-11-27 16:10:23 +00004141 POST_MEM_WRITE(ARG3, sizeof(int));
jsgf855d93d2003-10-13 22:26:55 +00004142 break;
nethercote73b526f2004-10-31 18:48:21 +00004143 case VKI_SNDCTL_SEQ_CTRLRATE:
4144 case VKI_SNDCTL_DSP_SPEED:
4145 case VKI_SNDCTL_DSP_STEREO:
4146 case VKI_SNDCTL_DSP_GETBLKSIZE:
4147 case VKI_SNDCTL_DSP_CHANNELS:
4148 case VKI_SOUND_PCM_WRITE_FILTER:
4149 case VKI_SNDCTL_DSP_SUBDIVIDE:
4150 case VKI_SNDCTL_DSP_SETFRAGMENT:
nethercote73b526f2004-10-31 18:48:21 +00004151 case VKI_SNDCTL_DSP_GETCHANNELMASK:
nethercote73b526f2004-10-31 18:48:21 +00004152 case VKI_SNDCTL_DSP_BIND_CHANNEL:
nethercote73b526f2004-10-31 18:48:21 +00004153 case VKI_SNDCTL_TMR_TIMEBASE:
4154 case VKI_SNDCTL_TMR_TEMPO:
4155 case VKI_SNDCTL_TMR_SOURCE:
4156 case VKI_SNDCTL_MIDI_PRETIME:
4157 case VKI_SNDCTL_MIDI_MPUMODE:
jsgf855d93d2003-10-13 22:26:55 +00004158 break;
nethercote73b526f2004-10-31 18:48:21 +00004159 case VKI_SNDCTL_DSP_GETOSPACE:
4160 case VKI_SNDCTL_DSP_GETISPACE:
njn22cfccb2004-11-27 16:10:23 +00004161 POST_MEM_WRITE(ARG3, sizeof(vki_audio_buf_info));
jsgf855d93d2003-10-13 22:26:55 +00004162 break;
nethercote73b526f2004-10-31 18:48:21 +00004163 case VKI_SNDCTL_DSP_SETTRIGGER:
jsgf855d93d2003-10-13 22:26:55 +00004164 break;
4165
nethercote73b526f2004-10-31 18:48:21 +00004166 case VKI_SNDCTL_DSP_POST:
4167 case VKI_SNDCTL_DSP_RESET:
4168 case VKI_SNDCTL_DSP_SYNC:
4169 case VKI_SNDCTL_DSP_SETSYNCRO:
4170 case VKI_SNDCTL_DSP_SETDUPLEX:
jsgf855d93d2003-10-13 22:26:55 +00004171 break;
4172
tom2f932882005-11-14 17:03:54 +00004173 /* linux/soundcard interface (ALSA) */
4174 case VKI_SNDRV_PCM_IOCTL_HW_FREE:
4175 case VKI_SNDRV_PCM_IOCTL_HWSYNC:
4176 case VKI_SNDRV_PCM_IOCTL_PREPARE:
4177 case VKI_SNDRV_PCM_IOCTL_RESET:
4178 case VKI_SNDRV_PCM_IOCTL_START:
4179 case VKI_SNDRV_PCM_IOCTL_DROP:
4180 case VKI_SNDRV_PCM_IOCTL_DRAIN:
4181 case VKI_SNDRV_PCM_IOCTL_RESUME:
4182 case VKI_SNDRV_PCM_IOCTL_XRUN:
4183 case VKI_SNDRV_PCM_IOCTL_UNLINK:
4184 case VKI_SNDRV_TIMER_IOCTL_START:
4185 case VKI_SNDRV_TIMER_IOCTL_STOP:
4186 case VKI_SNDRV_TIMER_IOCTL_CONTINUE:
4187 case VKI_SNDRV_TIMER_IOCTL_PAUSE:
4188 break;
4189
jsgf855d93d2003-10-13 22:26:55 +00004190 /* Real Time Clock (/dev/rtc) ioctls */
nethercote73b526f2004-10-31 18:48:21 +00004191 case VKI_RTC_UIE_ON:
4192 case VKI_RTC_UIE_OFF:
4193 case VKI_RTC_AIE_ON:
4194 case VKI_RTC_AIE_OFF:
4195 case VKI_RTC_PIE_ON:
4196 case VKI_RTC_PIE_OFF:
4197 case VKI_RTC_IRQP_SET:
jsgf855d93d2003-10-13 22:26:55 +00004198 break;
nethercote73b526f2004-10-31 18:48:21 +00004199 case VKI_RTC_RD_TIME:
4200 case VKI_RTC_ALM_READ:
njn22cfccb2004-11-27 16:10:23 +00004201 POST_MEM_WRITE(ARG3, sizeof(struct vki_rtc_time));
jsgf855d93d2003-10-13 22:26:55 +00004202 break;
nethercote73b526f2004-10-31 18:48:21 +00004203 case VKI_RTC_ALM_SET:
jsgf855d93d2003-10-13 22:26:55 +00004204 break;
nethercote73b526f2004-10-31 18:48:21 +00004205 case VKI_RTC_IRQP_READ:
njn22cfccb2004-11-27 16:10:23 +00004206 POST_MEM_WRITE(ARG3, sizeof(unsigned long));
jsgf855d93d2003-10-13 22:26:55 +00004207 break;
jsgf855d93d2003-10-13 22:26:55 +00004208
tomeafc49b2005-07-28 16:08:09 +00004209 /* Block devices */
4210 case VKI_BLKROSET:
4211 break;
4212 case VKI_BLKROGET:
4213 POST_MEM_WRITE(ARG3, sizeof(int));
4214 break;
nethercote95a97862004-11-06 16:31:43 +00004215 case VKI_BLKGETSIZE:
njn22cfccb2004-11-27 16:10:23 +00004216 POST_MEM_WRITE(ARG3, sizeof(unsigned long));
jsgf855d93d2003-10-13 22:26:55 +00004217 break;
tomeafc49b2005-07-28 16:08:09 +00004218 case VKI_BLKRASET:
4219 break;
4220 case VKI_BLKRAGET:
4221 POST_MEM_WRITE(ARG3, sizeof(long));
4222 break;
4223 case VKI_BLKFRASET:
4224 break;
4225 case VKI_BLKFRAGET:
4226 POST_MEM_WRITE(ARG3, sizeof(long));
4227 break;
4228 case VKI_BLKSECTGET:
4229 POST_MEM_WRITE(ARG3, sizeof(unsigned short));
4230 break;
4231 case VKI_BLKSSZGET:
4232 POST_MEM_WRITE(ARG3, sizeof(int));
4233 break;
4234 case VKI_BLKBSZGET:
4235 POST_MEM_WRITE(ARG3, sizeof(int));
4236 break;
4237 case VKI_BLKBSZSET:
4238 break;
tomd6555642005-07-18 13:26:55 +00004239 case VKI_BLKGETSIZE64:
4240 POST_MEM_WRITE(ARG3, sizeof(unsigned long long));
4241 break;
jsgf855d93d2003-10-13 22:26:55 +00004242
thughesacbbc322004-06-19 12:12:01 +00004243 /* Hard disks */
tom2c2bc252005-07-28 16:13:42 +00004244 case VKI_HDIO_GETGEO: /* 0x0301 */
4245 POST_MEM_WRITE(ARG3, sizeof(struct vki_hd_geometry));
4246 break;
nethercote73b526f2004-10-31 18:48:21 +00004247 case VKI_HDIO_GET_IDENTITY: /* 0x030d */
njn22cfccb2004-11-27 16:10:23 +00004248 POST_MEM_WRITE(ARG3, VKI_SIZEOF_STRUCT_HD_DRIVEID );
thughesacbbc322004-06-19 12:12:01 +00004249 break;
4250
jsgf855d93d2003-10-13 22:26:55 +00004251 /* CD ROM stuff (??) */
nethercote73b526f2004-10-31 18:48:21 +00004252 case VKI_CDROMSUBCHNL:
njn22cfccb2004-11-27 16:10:23 +00004253 POST_MEM_WRITE(ARG3, sizeof(struct vki_cdrom_subchnl));
jsgf855d93d2003-10-13 22:26:55 +00004254 break;
nethercote73b526f2004-10-31 18:48:21 +00004255 case VKI_CDROMREADTOCHDR:
njn22cfccb2004-11-27 16:10:23 +00004256 POST_MEM_WRITE(ARG3, sizeof(struct vki_cdrom_tochdr));
jsgf855d93d2003-10-13 22:26:55 +00004257 break;
nethercote73b526f2004-10-31 18:48:21 +00004258 case VKI_CDROMREADTOCENTRY:
njn22cfccb2004-11-27 16:10:23 +00004259 POST_MEM_WRITE(ARG3, sizeof(struct vki_cdrom_tochdr));
jsgf855d93d2003-10-13 22:26:55 +00004260 break;
nethercote73b526f2004-10-31 18:48:21 +00004261 case VKI_CDROMMULTISESSION:
njn22cfccb2004-11-27 16:10:23 +00004262 POST_MEM_WRITE(ARG3, sizeof(struct vki_cdrom_multisession));
thughes5b788fb2004-09-11 15:07:14 +00004263 break;
nethercote73b526f2004-10-31 18:48:21 +00004264 case VKI_CDROMVOLREAD:
njn22cfccb2004-11-27 16:10:23 +00004265 POST_MEM_WRITE(ARG3, sizeof(struct vki_cdrom_volctrl));
thughes5b788fb2004-09-11 15:07:14 +00004266 break;
nethercote73b526f2004-10-31 18:48:21 +00004267 case VKI_CDROMREADAUDIO:
thughes5b788fb2004-09-11 15:07:14 +00004268 {
njn22cfccb2004-11-27 16:10:23 +00004269 struct vki_cdrom_read_audio *cra = (struct vki_cdrom_read_audio *) ARG3;
nethercoteef0c7662004-11-06 15:38:43 +00004270 POST_MEM_WRITE( (Addr)(cra->buf), cra->nframes * VKI_CD_FRAMESIZE_RAW);
thughes5b788fb2004-09-11 15:07:14 +00004271 break;
4272 }
4273
nethercote73b526f2004-10-31 18:48:21 +00004274 case VKI_CDROMPLAYMSF:
jsgf855d93d2003-10-13 22:26:55 +00004275 break;
4276 /* The following two are probably bogus (should check args
4277 for readability). JRS 20021117 */
nethercote73b526f2004-10-31 18:48:21 +00004278 case VKI_CDROM_DRIVE_STATUS: /* 0x5326 */
4279 case VKI_CDROM_CLEAR_OPTIONS: /* 0x5321 */
jsgf855d93d2003-10-13 22:26:55 +00004280 break;
4281
nethercote73b526f2004-10-31 18:48:21 +00004282 case VKI_FIGETBSZ:
njn22cfccb2004-11-27 16:10:23 +00004283 POST_MEM_WRITE(ARG3, sizeof(unsigned long));
thughes66d80092004-06-19 12:41:05 +00004284 break;
nethercote73b526f2004-10-31 18:48:21 +00004285 case VKI_FIBMAP:
njn22cfccb2004-11-27 16:10:23 +00004286 POST_MEM_WRITE(ARG3, sizeof(unsigned long));
thughes66d80092004-06-19 12:41:05 +00004287 break;
4288
nethercote73b526f2004-10-31 18:48:21 +00004289 case VKI_FBIOGET_VSCREENINFO: //0x4600
njn22cfccb2004-11-27 16:10:23 +00004290 POST_MEM_WRITE(ARG3, sizeof(struct vki_fb_var_screeninfo));
thughes44e35582004-04-21 15:52:33 +00004291 break;
nethercote73b526f2004-10-31 18:48:21 +00004292 case VKI_FBIOGET_FSCREENINFO: //0x4602
njn22cfccb2004-11-27 16:10:23 +00004293 POST_MEM_WRITE(ARG3, sizeof(struct vki_fb_fix_screeninfo));
thughes44e35582004-04-21 15:52:33 +00004294 break;
4295
nethercote73b526f2004-10-31 18:48:21 +00004296 case VKI_PPCLAIM:
4297 case VKI_PPEXCL:
4298 case VKI_PPYIELD:
4299 case VKI_PPRELEASE:
4300 case VKI_PPSETMODE:
4301 case VKI_PPSETPHASE:
4302 case VKI_PPSETFLAGS:
4303 case VKI_PPWDATA:
4304 case VKI_PPWCONTROL:
4305 case VKI_PPFCONTROL:
4306 case VKI_PPDATADIR:
4307 case VKI_PPNEGOT:
4308 case VKI_PPWCTLONIRQ:
4309 case VKI_PPSETTIME:
thughesd9895482004-08-16 19:46:55 +00004310 break;
nethercote73b526f2004-10-31 18:48:21 +00004311 case VKI_PPGETMODE:
njn22cfccb2004-11-27 16:10:23 +00004312 POST_MEM_WRITE( ARG3, sizeof(int) );
thughesd9895482004-08-16 19:46:55 +00004313 break;
nethercote73b526f2004-10-31 18:48:21 +00004314 case VKI_PPGETPHASE:
njn22cfccb2004-11-27 16:10:23 +00004315 POST_MEM_WRITE( ARG3, sizeof(int) );
thughesd9895482004-08-16 19:46:55 +00004316 break;
nethercote73b526f2004-10-31 18:48:21 +00004317 case VKI_PPGETMODES:
njn22cfccb2004-11-27 16:10:23 +00004318 POST_MEM_WRITE( ARG3, sizeof(unsigned int) );
thughesd9895482004-08-16 19:46:55 +00004319 break;
nethercote73b526f2004-10-31 18:48:21 +00004320 case VKI_PPGETFLAGS:
njn22cfccb2004-11-27 16:10:23 +00004321 POST_MEM_WRITE( ARG3, sizeof(int) );
thughesd9895482004-08-16 19:46:55 +00004322 break;
nethercote73b526f2004-10-31 18:48:21 +00004323 case VKI_PPRSTATUS:
njn22cfccb2004-11-27 16:10:23 +00004324 POST_MEM_WRITE( ARG3, sizeof(unsigned char) );
thughesd9895482004-08-16 19:46:55 +00004325 break;
nethercote73b526f2004-10-31 18:48:21 +00004326 case VKI_PPRDATA:
njn22cfccb2004-11-27 16:10:23 +00004327 POST_MEM_WRITE( ARG3, sizeof(unsigned char) );
thughesd9895482004-08-16 19:46:55 +00004328 break;
nethercote73b526f2004-10-31 18:48:21 +00004329 case VKI_PPRCONTROL:
njn22cfccb2004-11-27 16:10:23 +00004330 POST_MEM_WRITE( ARG3, sizeof(unsigned char) );
thughesd9895482004-08-16 19:46:55 +00004331 break;
nethercote73b526f2004-10-31 18:48:21 +00004332 case VKI_PPCLRIRQ:
njn22cfccb2004-11-27 16:10:23 +00004333 POST_MEM_WRITE( ARG3, sizeof(int) );
thughesd9895482004-08-16 19:46:55 +00004334 break;
nethercote73b526f2004-10-31 18:48:21 +00004335 case VKI_PPGETTIME:
njn22cfccb2004-11-27 16:10:23 +00004336 POST_MEM_WRITE( ARG3, sizeof(struct vki_timeval) );
thughesd9895482004-08-16 19:46:55 +00004337 break;
4338
thughesc3b842d2004-11-13 10:38:04 +00004339 case VKI_GIO_FONT:
njn22cfccb2004-11-27 16:10:23 +00004340 POST_MEM_WRITE( ARG3, 32 * 256 );
thughesc3b842d2004-11-13 10:38:04 +00004341 break;
4342 case VKI_PIO_FONT:
4343 break;
4344
4345 case VKI_GIO_FONTX:
njn22cfccb2004-11-27 16:10:23 +00004346 POST_MEM_WRITE( (Addr)((struct vki_consolefontdesc *)ARG3)->chardata,
4347 32 * ((struct vki_consolefontdesc *)ARG3)->charcount );
thughesc3b842d2004-11-13 10:38:04 +00004348 break;
4349 case VKI_PIO_FONTX:
4350 break;
4351
4352 case VKI_PIO_FONTRESET:
4353 break;
4354
4355 case VKI_GIO_CMAP:
njn22cfccb2004-11-27 16:10:23 +00004356 POST_MEM_WRITE( ARG3, 16 * 3 );
thughesc3b842d2004-11-13 10:38:04 +00004357 break;
4358 case VKI_PIO_CMAP:
4359 break;
4360
4361 case VKI_KIOCSOUND:
4362 case VKI_KDMKTONE:
4363 break;
4364
4365 case VKI_KDGETLED:
njn22cfccb2004-11-27 16:10:23 +00004366 POST_MEM_WRITE( ARG3, sizeof(char) );
thughesc3b842d2004-11-13 10:38:04 +00004367 break;
4368 case VKI_KDSETLED:
4369 break;
4370
4371 case VKI_KDGKBTYPE:
njn22cfccb2004-11-27 16:10:23 +00004372 POST_MEM_WRITE( ARG3, sizeof(char) );
thughesc3b842d2004-11-13 10:38:04 +00004373 break;
4374
4375 case VKI_KDADDIO:
4376 case VKI_KDDELIO:
4377 case VKI_KDENABIO:
4378 case VKI_KDDISABIO:
4379 break;
4380
4381 case VKI_KDSETMODE:
4382 break;
4383 case VKI_KDGETMODE:
njn22cfccb2004-11-27 16:10:23 +00004384 POST_MEM_WRITE( ARG3, sizeof(int) );
thughesc3b842d2004-11-13 10:38:04 +00004385 break;
4386
4387 case VKI_KDMAPDISP:
4388 case VKI_KDUNMAPDISP:
4389 break;
4390
4391 case VKI_GIO_SCRNMAP:
njn22cfccb2004-11-27 16:10:23 +00004392 POST_MEM_WRITE( ARG3, VKI_E_TABSZ );
thughesc3b842d2004-11-13 10:38:04 +00004393 break;
4394 case VKI_PIO_SCRNMAP:
4395 break;
4396 case VKI_GIO_UNISCRNMAP:
njn22cfccb2004-11-27 16:10:23 +00004397 POST_MEM_WRITE( ARG3, VKI_E_TABSZ * sizeof(unsigned short) );
thughesc3b842d2004-11-13 10:38:04 +00004398 break;
4399 case VKI_PIO_UNISCRNMAP:
4400 break;
4401
4402 case VKI_KDGKBMODE:
njn22cfccb2004-11-27 16:10:23 +00004403 POST_MEM_WRITE( ARG3, sizeof(int) );
thughesc3b842d2004-11-13 10:38:04 +00004404 break;
4405 case VKI_KDSKBMODE:
4406 break;
4407
4408 case VKI_KDGKBMETA:
njn22cfccb2004-11-27 16:10:23 +00004409 POST_MEM_WRITE( ARG3, sizeof(int) );
thughesc3b842d2004-11-13 10:38:04 +00004410 break;
4411 case VKI_KDSKBMETA:
4412 break;
4413
4414 case VKI_KDGKBLED:
njn22cfccb2004-11-27 16:10:23 +00004415 POST_MEM_WRITE( ARG3, sizeof(char) );
thughesc3b842d2004-11-13 10:38:04 +00004416 break;
4417 case VKI_KDSKBLED:
4418 break;
4419
4420 case VKI_KDGKBENT:
njn22cfccb2004-11-27 16:10:23 +00004421 POST_MEM_WRITE( (Addr)&((struct vki_kbentry *)ARG3)->kb_value,
4422 sizeof(((struct vki_kbentry *)ARG3)->kb_value) );
thughesc3b842d2004-11-13 10:38:04 +00004423 break;
4424 case VKI_KDSKBENT:
4425 break;
4426
4427 case VKI_KDGKBSENT:
njn22cfccb2004-11-27 16:10:23 +00004428 POST_MEM_WRITE( (Addr)((struct vki_kbsentry *)ARG3)->kb_string,
4429 sizeof(((struct vki_kbsentry *)ARG3)->kb_string) );
thughesc3b842d2004-11-13 10:38:04 +00004430 break;
4431 case VKI_KDSKBSENT:
4432 break;
4433
4434 case VKI_KDGKBDIACR:
njn22cfccb2004-11-27 16:10:23 +00004435 POST_MEM_WRITE( ARG3, sizeof(struct vki_kbdiacrs) );
thughesc3b842d2004-11-13 10:38:04 +00004436 break;
4437 case VKI_KDSKBDIACR:
4438 break;
4439
4440 case VKI_KDGETKEYCODE:
njn22cfccb2004-11-27 16:10:23 +00004441 POST_MEM_WRITE( (Addr)((struct vki_kbkeycode *)ARG3)->keycode,
4442 sizeof(((struct vki_kbkeycode *)ARG3)->keycode) );
thughesc3b842d2004-11-13 10:38:04 +00004443 break;
4444 case VKI_KDSETKEYCODE:
4445 break;
4446
4447 case VKI_KDSIGACCEPT:
4448 break;
4449
4450 case VKI_KDKBDREP:
4451 break;
4452
jsgf855d93d2003-10-13 22:26:55 +00004453 /* We don't have any specific information on it, so
4454 try to do something reasonable based on direction and
4455 size bits. The encoding scheme is described in
4456 /usr/include/asm/ioctl.h.
4457
4458 According to Simon Hausmann, _IOC_READ means the kernel
4459 writes a value to the ioctl value passed from the user
4460 space and the other way around with _IOC_WRITE. */
4461 default: {
njn22cfccb2004-11-27 16:10:23 +00004462 UInt dir = _VKI_IOC_DIR(ARG2);
4463 UInt size = _VKI_IOC_SIZE(ARG2);
nethercote73b526f2004-10-31 18:48:21 +00004464 if (size > 0 && (dir & _VKI_IOC_READ)
sewardja8d8e232005-06-07 20:04:56 +00004465 && RES == 0
njn22cfccb2004-11-27 16:10:23 +00004466 && ARG3 != (Addr)NULL)
4467 POST_MEM_WRITE(ARG3, size);
jsgf855d93d2003-10-13 22:26:55 +00004468 break;
4469 }
4470 }
4471}
4472
njn03f1e582005-03-26 20:08:06 +00004473/*
4474 If we're sending a SIGKILL to one of our own threads, then simulate
4475 it rather than really sending the signal, so that the target thread
4476 gets a chance to clean up. Returns True if we did the killing (or
4477 no killing is necessary), and False if the caller should use the
4478 normal kill syscall.
4479
4480 "pid" is any pid argument which can be passed to kill; group kills
4481 (< -1, 0), and owner kills (-1) are ignored, on the grounds that
4482 they'll most likely hit all the threads and we won't need to worry
4483 about cleanup. In truth, we can't fully emulate these multicast
4484 kills.
4485
4486 "tgid" is a thread group id. If it is not -1, then the target
4487 thread must be in that thread group.
4488 */
sewardj7eb7c582005-06-23 01:02:53 +00004489Bool ML_(do_sigkill)(Int pid, Int tgid)
njn03f1e582005-03-26 20:08:06 +00004490{
4491 ThreadState *tst;
4492 ThreadId tid;
4493
4494 if (pid <= 0)
4495 return False;
4496
4497 tid = VG_(get_lwp_tid)(pid);
4498 if (tid == VG_INVALID_THREADID)
4499 return False; /* none of our threads */
4500
4501 tst = VG_(get_ThreadState)(tid);
4502 if (tst == NULL || tst->status == VgTs_Empty)
4503 return False; /* hm, shouldn't happen */
4504
4505 if (tgid != -1 && tst->os_state.threadgroup != tgid)
4506 return False; /* not the right thread group */
4507
4508 /* Check to see that the target isn't already exiting. */
4509 if (!VG_(is_exiting)(tid)) {
4510 if (VG_(clo_trace_signals))
sewardja8d8e232005-06-07 20:04:56 +00004511 VG_(message)(Vg_DebugMsg, "Thread %d being killed with SIGKILL",
4512 tst->tid);
njn03f1e582005-03-26 20:08:06 +00004513
4514 tst->exitreason = VgSrc_FatalSig;
4515 tst->os_state.fatalsig = VKI_SIGKILL;
4516
4517 if (!VG_(is_running_thread)(tid))
4518 VG_(kill_thread)(tid);
4519 }
4520
4521 return True;
4522}
4523
sewardja8d8e232005-06-07 20:04:56 +00004524PRE(sys_kill)
jsgf855d93d2003-10-13 22:26:55 +00004525{
njn22cfccb2004-11-27 16:10:23 +00004526 PRINT("sys_kill ( %d, %d )", ARG1,ARG2);
nethercote9a3beb92004-11-12 17:07:26 +00004527 PRE_REG_READ2(long, "kill", int, pid, int, sig);
sewardj7eb7c582005-06-23 01:02:53 +00004528 if (!ML_(client_signal_OK)(ARG2)) {
sewardja8d8e232005-06-07 20:04:56 +00004529 SET_STATUS_Failure( VKI_EINVAL );
njn03f1e582005-03-26 20:08:06 +00004530 return;
4531 }
jsgf855d93d2003-10-13 22:26:55 +00004532
njn03f1e582005-03-26 20:08:06 +00004533 /* If we're sending SIGKILL, check to see if the target is one of
4534 our threads and handle it specially. */
sewardj7eb7c582005-06-23 01:02:53 +00004535 if (ARG2 == VKI_SIGKILL && ML_(do_sigkill)(ARG1, -1))
sewardja8d8e232005-06-07 20:04:56 +00004536 SET_STATUS_Success(0);
njn03f1e582005-03-26 20:08:06 +00004537 else
sewardja8d8e232005-06-07 20:04:56 +00004538 SET_STATUS_from_SysRes( VG_(do_syscall2)(SYSNO, ARG1, ARG2) );
njn03f1e582005-03-26 20:08:06 +00004539
sewardjb5f6f512005-03-10 23:59:00 +00004540 if (VG_(clo_trace_signals))
4541 VG_(message)(Vg_DebugMsg, "kill: sent signal %d to pid %d",
njn03f1e582005-03-26 20:08:06 +00004542 ARG2, ARG1);
sewardja8d8e232005-06-07 20:04:56 +00004543
4544 /* This kill might have given us a pending signal. Ask for a check once
4545 the syscall is done. */
4546 *flags |= SfPollAfter;
jsgf855d93d2003-10-13 22:26:55 +00004547}
4548
sewardja8d8e232005-06-07 20:04:56 +00004549PRE(sys_link)
jsgf855d93d2003-10-13 22:26:55 +00004550{
sewardja8d8e232005-06-07 20:04:56 +00004551 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00004552 PRINT("sys_link ( %p, %p)", ARG1, ARG2);
nethercotec6851dd2004-11-11 18:00:47 +00004553 PRE_REG_READ2(long, "link", const char *, oldpath, const char *, newpath);
njn22cfccb2004-11-27 16:10:23 +00004554 PRE_MEM_RASCIIZ( "link(oldpath)", ARG1);
4555 PRE_MEM_RASCIIZ( "link(newpath)", ARG2);
jsgf855d93d2003-10-13 22:26:55 +00004556}
4557
sewardj696c5512005-06-08 23:38:32 +00004558PRE(sys_newlstat)
4559{
4560 PRINT("sys_newlstat ( %p(%s), %p )", ARG1,ARG1,ARG2);
4561 PRE_REG_READ2(long, "lstat", char *, file_name, struct stat *, buf);
4562 PRE_MEM_RASCIIZ( "lstat(file_name)", ARG1 );
4563 PRE_MEM_WRITE( "lstat(buf)", ARG2, sizeof(struct vki_stat) );
4564}
4565
4566POST(sys_newlstat)
4567{
4568 vg_assert(SUCCESS);
4569 if (RES == 0) {
4570 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
4571 }
4572}
jsgf855d93d2003-10-13 22:26:55 +00004573
sewardja8d8e232005-06-07 20:04:56 +00004574PRE(sys_mkdir)
jsgf855d93d2003-10-13 22:26:55 +00004575{
sewardja8d8e232005-06-07 20:04:56 +00004576 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00004577 PRINT("sys_mkdir ( %p, %d )", ARG1,ARG2);
nethercote9a3beb92004-11-12 17:07:26 +00004578 PRE_REG_READ2(long, "mkdir", const char *, pathname, int, mode);
njn22cfccb2004-11-27 16:10:23 +00004579 PRE_MEM_RASCIIZ( "mkdir(pathname)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00004580}
4581
sewardja8d8e232005-06-07 20:04:56 +00004582PRE(sys_mprotect)
jsgf855d93d2003-10-13 22:26:55 +00004583{
njn22cfccb2004-11-27 16:10:23 +00004584 PRINT("sys_mprotect ( %p, %llu, %d )", ARG1,(ULong)ARG2,ARG3);
nethercote06c7bd72004-11-14 19:11:56 +00004585 PRE_REG_READ3(long, "mprotect",
4586 unsigned long, addr, vki_size_t, len, unsigned long, prot);
fitzhardinge98abfc72003-12-16 02:05:15 +00004587
tom65505192005-11-08 16:51:55 +00004588 if (!ML_(valid_client_addr)(ARG1, ARG2, tid, "mprotect")) {
sewardja8d8e232005-06-07 20:04:56 +00004589 SET_STATUS_Failure( VKI_ENOMEM );
sewardj337556e2005-11-09 14:51:59 +00004590 }
4591 else
4592 if (ARG3 & (VKI_PROT_GROWSDOWN|VKI_PROT_GROWSUP)) {
4593 /* Deal with mprotects on growable stack areas.
4594
4595 The critical files to understand all this are mm/mprotect.c
4596 in the kernel and sysdeps/unix/sysv/linux/dl-execstack.c in
4597 glibc.
4598
4599 The kernel provides PROT_GROWSDOWN and PROT_GROWSUP which
4600 round the start/end address of mprotect to the start/end of
4601 the underlying vma and glibc uses that as an easy way to
4602 change the protection of the stack by calling mprotect on the
4603 last page of the stack with PROT_GROWSDOWN set.
4604
4605 The sanity check provided by the kernel is that the vma must
4606 have the VM_GROWSDOWN/VM_GROWSUP flag set as appropriate. */
tom65505192005-11-08 16:51:55 +00004607 UInt grows = ARG3 & (VKI_PROT_GROWSDOWN|VKI_PROT_GROWSUP);
4608 NSegment *aseg = VG_(am_find_nsegment)(ARG1);
4609 NSegment *rseg;
4610
4611 vg_assert(aseg);
4612
4613 if (grows == VKI_PROT_GROWSDOWN) {
4614 rseg = VG_(am_next_nsegment)( aseg, False/*backwards*/ );
4615 if (rseg &&
4616 rseg->kind == SkResvn &&
4617 rseg->smode == SmUpper &&
4618 rseg->end+1 == aseg->start) {
4619 Addr end = ARG1 + ARG2;
4620 ARG1 = aseg->start;
4621 ARG2 = end - aseg->start;
4622 ARG3 &= ~VKI_PROT_GROWSDOWN;
4623 } else {
4624 SET_STATUS_Failure( VKI_EINVAL );
4625 }
4626 } else if (grows == VKI_PROT_GROWSUP) {
4627 rseg = VG_(am_next_nsegment)( aseg, True/*forwards*/ );
4628 if (rseg &&
4629 rseg->kind == SkResvn &&
4630 rseg->smode == SmLower &&
4631 aseg->end+1 == rseg->start) {
4632 ARG2 = aseg->end - ARG1 + 1;
4633 ARG3 &= ~VKI_PROT_GROWSUP;
4634 } else {
4635 SET_STATUS_Failure( VKI_EINVAL );
4636 }
4637 } else {
sewardj337556e2005-11-09 14:51:59 +00004638 /* both GROWSUP and GROWSDOWN */
tom65505192005-11-08 16:51:55 +00004639 SET_STATUS_Failure( VKI_EINVAL );
4640 }
4641 }
jsgf855d93d2003-10-13 22:26:55 +00004642}
4643
nethercote85a456f2004-11-16 17:31:56 +00004644POST(sys_mprotect)
jsgf855d93d2003-10-13 22:26:55 +00004645{
njn22cfccb2004-11-27 16:10:23 +00004646 Addr a = ARG1;
4647 SizeT len = ARG2;
4648 Int prot = ARG3;
sewardj45f4e7c2005-09-27 19:20:21 +00004649 Bool rr = toBool(prot & VKI_PROT_READ);
4650 Bool ww = toBool(prot & VKI_PROT_WRITE);
4651 Bool xx = toBool(prot & VKI_PROT_EXEC);
4652 Bool d;
nethercote27ea8bc2004-07-10 17:21:14 +00004653
sewardj45f4e7c2005-09-27 19:20:21 +00004654 page_align_addr_and_len(&a, &len);
4655 d = VG_(am_notify_mprotect)(a, len, prot);
nethercote27ea8bc2004-07-10 17:21:14 +00004656 VG_TRACK( change_mem_mprotect, a, len, rr, ww, xx );
sewardj45f4e7c2005-09-27 19:20:21 +00004657 VG_(di_notify_mprotect)( a, len, prot );
4658 if (d)
4659 VG_(discard_translations)( (Addr64)a, (ULong)len,
4660 "POST(sys_mprotect)" );
jsgf855d93d2003-10-13 22:26:55 +00004661}
4662
sewardja8d8e232005-06-07 20:04:56 +00004663PRE(sys_munmap)
jsgf855d93d2003-10-13 22:26:55 +00004664{
sewardja8d8e232005-06-07 20:04:56 +00004665 if (0) VG_(printf)(" munmap( %p )\n", ARG1);
njn22cfccb2004-11-27 16:10:23 +00004666 PRINT("sys_munmap ( %p, %llu )", ARG1,(ULong)ARG2);
nethercote06c7bd72004-11-14 19:11:56 +00004667 PRE_REG_READ2(long, "munmap", unsigned long, start, vki_size_t, length);
fitzhardinge98abfc72003-12-16 02:05:15 +00004668
sewardj7eb7c582005-06-23 01:02:53 +00004669 if (!ML_(valid_client_addr)(ARG1, ARG2, tid, "munmap"))
sewardja8d8e232005-06-07 20:04:56 +00004670 SET_STATUS_Failure( VKI_EINVAL );
jsgf855d93d2003-10-13 22:26:55 +00004671}
4672
nethercote85a456f2004-11-16 17:31:56 +00004673POST(sys_munmap)
jsgf855d93d2003-10-13 22:26:55 +00004674{
njn22cfccb2004-11-27 16:10:23 +00004675 Addr a = ARG1;
4676 SizeT len = ARG2;
sewardj45f4e7c2005-09-27 19:20:21 +00004677 Bool d;
nethercote27ea8bc2004-07-10 17:21:14 +00004678
sewardj45f4e7c2005-09-27 19:20:21 +00004679 page_align_addr_and_len(&a, &len);
4680 d = VG_(am_notify_munmap)(a, len);
nethercote27ea8bc2004-07-10 17:21:14 +00004681 VG_TRACK( die_mem_munmap, a, len );
sewardj45f4e7c2005-09-27 19:20:21 +00004682 VG_(di_notify_munmap)( a, len );
4683 if (d)
4684 VG_(discard_translations)( (Addr64)a, (ULong)len,
4685 "POST(sys_munmap)" );
jsgf855d93d2003-10-13 22:26:55 +00004686}
4687
sewardje6d5e722005-06-10 10:27:55 +00004688PRE(sys_mincore)
4689{
4690 PRINT("sys_mincore ( %p, %llu, %p )", ARG1,(ULong)ARG2,ARG3);
4691 PRE_REG_READ3(long, "mincore",
4692 unsigned long, start, vki_size_t, length,
4693 unsigned char *, vec);
njncdaec512005-06-30 00:16:02 +00004694 PRE_MEM_WRITE( "mincore(vec)", ARG3, VG_PGROUNDUP(ARG2) / VKI_PAGE_SIZE );
sewardje6d5e722005-06-10 10:27:55 +00004695}
4696POST(sys_mincore)
4697{
njncdaec512005-06-30 00:16:02 +00004698 POST_MEM_WRITE( ARG3, VG_PGROUNDUP(ARG2) / VKI_PAGE_SIZE );
sewardje6d5e722005-06-10 10:27:55 +00004699}
mueller6ceb2312004-01-02 22:52:34 +00004700
sewardja8d8e232005-06-07 20:04:56 +00004701PRE(sys_nanosleep)
mueller6ceb2312004-01-02 22:52:34 +00004702{
sewardja8d8e232005-06-07 20:04:56 +00004703 *flags |= SfMayBlock|SfPostOnFail;
njn22cfccb2004-11-27 16:10:23 +00004704 PRINT("sys_nanosleep ( %p, %p )", ARG1,ARG2);
nethercote5b653bc2004-11-15 14:32:12 +00004705 PRE_REG_READ2(long, "nanosleep",
4706 struct timespec *, req, struct timespec *, rem);
njn22cfccb2004-11-27 16:10:23 +00004707 PRE_MEM_READ( "nanosleep(req)", ARG1, sizeof(struct vki_timespec) );
4708 if (ARG2 != 0)
4709 PRE_MEM_WRITE( "nanosleep(rem)", ARG2, sizeof(struct vki_timespec) );
jsgf855d93d2003-10-13 22:26:55 +00004710}
4711
nethercote85a456f2004-11-16 17:31:56 +00004712POST(sys_nanosleep)
jsgf855d93d2003-10-13 22:26:55 +00004713{
sewardja8d8e232005-06-07 20:04:56 +00004714 vg_assert(SUCCESS || FAILURE);
4715 if (ARG2 != 0 && FAILURE && RES_unchecked == VKI_EINTR)
njn22cfccb2004-11-27 16:10:23 +00004716 POST_MEM_WRITE( ARG2, sizeof(struct vki_timespec) );
jsgf855d93d2003-10-13 22:26:55 +00004717}
4718
sewardja8d8e232005-06-07 20:04:56 +00004719PRE(sys_open)
jsgf855d93d2003-10-13 22:26:55 +00004720{
sewardj45f4e7c2005-09-27 19:20:21 +00004721 HChar name[30];
4722 SysRes sres;
4723
njn22cfccb2004-11-27 16:10:23 +00004724 if (ARG2 & VKI_O_CREAT) {
nethercotee824cc42004-11-09 16:20:46 +00004725 // 3-arg version
njn22cfccb2004-11-27 16:10:23 +00004726 PRINT("sys_open ( %p(%s), %d, %d )",ARG1,ARG1,ARG2,ARG3);
nethercotee824cc42004-11-09 16:20:46 +00004727 PRE_REG_READ3(long, "open",
nethercote0df495a2004-11-11 16:38:21 +00004728 const char *, filename, int, flags, int, mode);
nethercotee70bd7d2004-08-18 14:37:17 +00004729 } else {
nethercotee824cc42004-11-09 16:20:46 +00004730 // 2-arg version
njn22cfccb2004-11-27 16:10:23 +00004731 PRINT("sys_open ( %p(%s), %d )",ARG1,ARG1,ARG2);
nethercotee824cc42004-11-09 16:20:46 +00004732 PRE_REG_READ2(long, "open",
nethercote0df495a2004-11-11 16:38:21 +00004733 const char *, filename, int, flags);
nethercotee70bd7d2004-08-18 14:37:17 +00004734 }
njn22cfccb2004-11-27 16:10:23 +00004735 PRE_MEM_RASCIIZ( "open(filename)", ARG1 );
sewardj45f4e7c2005-09-27 19:20:21 +00004736
4737 /* Handle the case where the open is of /proc/self/cmdline or
4738 /proc/<pid>/cmdline, and just give it a copy of the fd for the
4739 fake file we cooked up at startup (in m_main). Also, seek the
4740 cloned fd back to the start. */
4741
4742 VG_(sprintf)(name, "/proc/%d/cmdline", VG_(getpid)());
4743 if (ML_(safe_to_deref)( (void*)ARG1, 1 )
4744 && (VG_(strcmp)((Char *)ARG1, name) == 0
4745 || VG_(strcmp)((Char *)ARG1, "/proc/self/cmdline") == 0)) {
4746 sres = VG_(dup)( VG_(cl_cmdline_fd) );
4747 SET_STATUS_from_SysRes( sres );
4748 if (!sres.isError) {
4749 OffT off = VG_(lseek)( sres.val, 0, VKI_SEEK_SET );
tomf4c23102005-10-31 17:05:21 +00004750 if (off < 0)
sewardj45f4e7c2005-09-27 19:20:21 +00004751 SET_STATUS_Failure( VKI_EMFILE );
4752 }
4753 return;
4754 }
4755
4756 /* Otherwise handle normally */
4757 *flags |= SfMayBlock;
jsgf855d93d2003-10-13 22:26:55 +00004758}
4759
nethercote85a456f2004-11-16 17:31:56 +00004760POST(sys_open)
jsgf855d93d2003-10-13 22:26:55 +00004761{
sewardja8d8e232005-06-07 20:04:56 +00004762 vg_assert(SUCCESS);
sewardj7eb7c582005-06-23 01:02:53 +00004763 if (!ML_(fd_allowed)(RES, "open", tid, True)) {
njn22cfccb2004-11-27 16:10:23 +00004764 VG_(close)(RES);
sewardja8d8e232005-06-07 20:04:56 +00004765 SET_STATUS_Failure( VKI_EMFILE );
rjwalshf5f536f2003-11-17 17:45:00 +00004766 } else {
nethercote493dd182004-02-24 23:57:47 +00004767 if (VG_(clo_track_fds))
njn4279a882005-08-26 03:43:28 +00004768 ML_(record_fd_open_with_given_name)(tid, RES, (Char*)ARG1);
jsgf855d93d2003-10-13 22:26:55 +00004769 }
jsgf855d93d2003-10-13 22:26:55 +00004770}
4771
sewardja8d8e232005-06-07 20:04:56 +00004772PRE(sys_read)
jsgf855d93d2003-10-13 22:26:55 +00004773{
sewardja8d8e232005-06-07 20:04:56 +00004774 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00004775 PRINT("sys_read ( %d, %p, %llu )", ARG1, ARG2, (ULong)ARG3);
nethercote8b76fe52004-11-08 19:20:09 +00004776 PRE_REG_READ3(ssize_t, "read",
njnca0518d2004-11-26 19:34:36 +00004777 unsigned int, fd, char *, buf, vki_size_t, count);
jsgf855d93d2003-10-13 22:26:55 +00004778
sewardj7eb7c582005-06-23 01:02:53 +00004779 if (!ML_(fd_allowed)(ARG1, "read", tid, False))
sewardja8d8e232005-06-07 20:04:56 +00004780 SET_STATUS_Failure( VKI_EBADF );
thughes26ab77b2004-08-14 12:10:49 +00004781 else
njn22cfccb2004-11-27 16:10:23 +00004782 PRE_MEM_WRITE( "read(buf)", ARG2, ARG3 );
jsgf855d93d2003-10-13 22:26:55 +00004783}
4784
nethercote85a456f2004-11-16 17:31:56 +00004785POST(sys_read)
jsgf855d93d2003-10-13 22:26:55 +00004786{
sewardja8d8e232005-06-07 20:04:56 +00004787 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00004788 POST_MEM_WRITE( ARG2, RES );
jsgf855d93d2003-10-13 22:26:55 +00004789}
4790
sewardja8d8e232005-06-07 20:04:56 +00004791PRE(sys_write)
jsgf855d93d2003-10-13 22:26:55 +00004792{
sewardj45f4e7c2005-09-27 19:20:21 +00004793 Bool ok;
sewardja8d8e232005-06-07 20:04:56 +00004794 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00004795 PRINT("sys_write ( %d, %p, %llu )", ARG1, ARG2, (ULong)ARG3);
nethercote8b76fe52004-11-08 19:20:09 +00004796 PRE_REG_READ3(ssize_t, "write",
njnca0518d2004-11-26 19:34:36 +00004797 unsigned int, fd, const char *, buf, vki_size_t, count);
sewardj45f4e7c2005-09-27 19:20:21 +00004798 /* check to see if it is allowed. If not, try for an exemption from
njn628add62005-11-12 18:21:40 +00004799 --sim-hints=enable-outer (used for self hosting). */
sewardj45f4e7c2005-09-27 19:20:21 +00004800 ok = ML_(fd_allowed)(ARG1, "write", tid, False);
4801 if (!ok && ARG1 == 2/*stderr*/
njn628add62005-11-12 18:21:40 +00004802 && VG_(strstr)(VG_(clo_sim_hints),"enable-outer"))
sewardj45f4e7c2005-09-27 19:20:21 +00004803 ok = True;
4804 if (!ok)
sewardja8d8e232005-06-07 20:04:56 +00004805 SET_STATUS_Failure( VKI_EBADF );
jsgf855d93d2003-10-13 22:26:55 +00004806 else
njn22cfccb2004-11-27 16:10:23 +00004807 PRE_MEM_READ( "write(buf)", ARG2, ARG3 );
jsgf855d93d2003-10-13 22:26:55 +00004808}
4809
sewardja8d8e232005-06-07 20:04:56 +00004810PRE(sys_creat)
jsgf855d93d2003-10-13 22:26:55 +00004811{
sewardja8d8e232005-06-07 20:04:56 +00004812 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00004813 PRINT("sys_creat ( %p(%s), %d )", ARG1,ARG1,ARG2);
nethercotec6851dd2004-11-11 18:00:47 +00004814 PRE_REG_READ2(long, "creat", const char *, pathname, int, mode);
njn22cfccb2004-11-27 16:10:23 +00004815 PRE_MEM_RASCIIZ( "creat(pathname)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00004816}
4817
nethercote85a456f2004-11-16 17:31:56 +00004818POST(sys_creat)
jsgf855d93d2003-10-13 22:26:55 +00004819{
sewardja8d8e232005-06-07 20:04:56 +00004820 vg_assert(SUCCESS);
sewardj7eb7c582005-06-23 01:02:53 +00004821 if (!ML_(fd_allowed)(RES, "creat", tid, True)) {
njn22cfccb2004-11-27 16:10:23 +00004822 VG_(close)(RES);
sewardja8d8e232005-06-07 20:04:56 +00004823 SET_STATUS_Failure( VKI_EMFILE );
rjwalshf5f536f2003-11-17 17:45:00 +00004824 } else {
nethercote493dd182004-02-24 23:57:47 +00004825 if (VG_(clo_track_fds))
njn4279a882005-08-26 03:43:28 +00004826 ML_(record_fd_open_with_given_name)(tid, RES, (Char*)ARG1);
jsgf855d93d2003-10-13 22:26:55 +00004827 }
jsgf855d93d2003-10-13 22:26:55 +00004828}
4829
nethercotef90953e2004-11-15 14:50:02 +00004830// XXX: x86-specific, due to pollfd struct
sewardja8d8e232005-06-07 20:04:56 +00004831PRE(sys_poll)
jsgf855d93d2003-10-13 22:26:55 +00004832{
4833 /* struct pollfd {
nethercoteef0c7662004-11-06 15:38:43 +00004834 int fd; -- file descriptor
4835 short events; -- requested events
4836 short revents; -- returned events
jsgf855d93d2003-10-13 22:26:55 +00004837 };
nethercoteeb0592d2004-11-05 12:02:27 +00004838 int poll(struct pollfd *ufds, unsigned int nfds, int timeout)
jsgf855d93d2003-10-13 22:26:55 +00004839 */
nethercoteeb0592d2004-11-05 12:02:27 +00004840 UInt i;
njn22cfccb2004-11-27 16:10:23 +00004841 struct vki_pollfd* ufds = (struct vki_pollfd *)ARG1;
tom60a4b0b2005-10-12 10:45:27 +00004842 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00004843 PRINT("sys_poll ( %p, %d, %d )\n", ARG1,ARG2,ARG3);
nethercotef90953e2004-11-15 14:50:02 +00004844 PRE_REG_READ3(long, "poll",
4845 struct pollfd *, ufds, unsigned int, nfds, long, timeout);
nethercoteef0c7662004-11-06 15:38:43 +00004846
njn22cfccb2004-11-27 16:10:23 +00004847 for (i = 0; i < ARG2; i++) {
nethercoteeb0592d2004-11-05 12:02:27 +00004848 // 'fd' and 'events' field are inputs; 'revents' is output.
4849 // XXX: this is x86 specific -- the pollfd struct varies across
4850 // different architectures.
nethercoteef0c7662004-11-06 15:38:43 +00004851 PRE_MEM_READ( "poll(ufds)",
4852 (Addr)(&ufds[i]), sizeof(int) + sizeof(short) );
4853 PRE_MEM_WRITE( "poll(ufds)", (Addr)(&ufds[i].revents), sizeof(short) );
4854 }
jsgf855d93d2003-10-13 22:26:55 +00004855}
4856
nethercote85a456f2004-11-16 17:31:56 +00004857POST(sys_poll)
jsgf855d93d2003-10-13 22:26:55 +00004858{
njn22cfccb2004-11-27 16:10:23 +00004859 if (RES > 0) {
jsgf855d93d2003-10-13 22:26:55 +00004860 UInt i;
njn22cfccb2004-11-27 16:10:23 +00004861 struct vki_pollfd* ufds = (struct vki_pollfd *)ARG1;
nethercoteeb0592d2004-11-05 12:02:27 +00004862 // XXX: again, this is x86-specific
njn22cfccb2004-11-27 16:10:23 +00004863 for (i = 0; i < ARG2; i++)
nethercoteef0c7662004-11-06 15:38:43 +00004864 POST_MEM_WRITE( (Addr)(&ufds[i].revents), sizeof(Short) );
jsgf855d93d2003-10-13 22:26:55 +00004865 }
4866}
4867
sewardja8d8e232005-06-07 20:04:56 +00004868PRE(sys_readlink)
jsgf855d93d2003-10-13 22:26:55 +00004869{
sewardj144c56d2005-09-30 01:09:50 +00004870 HChar name[25];
4871 Word saved = SYSNO;
4872
njn22cfccb2004-11-27 16:10:23 +00004873 PRINT("sys_readlink ( %p, %p, %llu )", ARG1,ARG2,(ULong)ARG3);
nethercote5a945af2004-11-14 18:37:07 +00004874 PRE_REG_READ3(long, "readlink",
4875 const char *, path, char *, buf, int, bufsiz);
njn22cfccb2004-11-27 16:10:23 +00004876 PRE_MEM_RASCIIZ( "readlink(path)", ARG1 );
4877 PRE_MEM_WRITE( "readlink(buf)", ARG2,ARG3 );
jsgf855d93d2003-10-13 22:26:55 +00004878
rjwalsh17d85302004-11-18 22:56:09 +00004879 /*
rjwalsh093047d2004-11-19 02:11:56 +00004880 * Handle the case where readlink is looking at /proc/self/exe or
4881 * /proc/<pid>/exe.
rjwalsh17d85302004-11-18 22:56:09 +00004882 */
sewardj144c56d2005-09-30 01:09:50 +00004883 VG_(sprintf)(name, "/proc/%d/exe", VG_(getpid)());
sewardjca7a4752005-09-30 10:32:39 +00004884 if (ML_(safe_to_deref)((void*)ARG1, 1)
sewardje226b382005-09-30 01:47:12 +00004885 && (VG_(strcmp)((Char *)ARG1, name) == 0
4886 || VG_(strcmp)((Char *)ARG1, "/proc/self/exe") == 0)) {
sewardj144c56d2005-09-30 01:09:50 +00004887 VG_(sprintf)(name, "/proc/self/fd/%d", VG_(cl_exec_fd));
4888 SET_STATUS_from_SysRes( VG_(do_syscall3)(saved, (UWord)name,
4889 ARG2, ARG3));
4890 } else {
4891 /* Normal case */
4892 SET_STATUS_from_SysRes( VG_(do_syscall3)(saved, ARG1, ARG2, ARG3));
rjwalsh17d85302004-11-18 22:56:09 +00004893 }
4894
sewardja8d8e232005-06-07 20:04:56 +00004895 if (SUCCESS && RES > 0)
njn22cfccb2004-11-27 16:10:23 +00004896 POST_MEM_WRITE( ARG2, RES );
jsgf855d93d2003-10-13 22:26:55 +00004897}
4898
sewardja8d8e232005-06-07 20:04:56 +00004899PRE(sys_readv)
jsgf855d93d2003-10-13 22:26:55 +00004900{
jsgf855d93d2003-10-13 22:26:55 +00004901 Int i;
nethercote73b526f2004-10-31 18:48:21 +00004902 struct vki_iovec * vec;
sewardja8d8e232005-06-07 20:04:56 +00004903 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00004904 PRINT("sys_readv ( %d, %p, %llu )",ARG1,ARG2,(ULong)ARG3);
nethercoted6b5a212004-11-15 17:04:14 +00004905 PRE_REG_READ3(ssize_t, "readv",
4906 unsigned long, fd, const struct iovec *, vector,
4907 unsigned long, count);
sewardj7eb7c582005-06-23 01:02:53 +00004908 if (!ML_(fd_allowed)(ARG1, "readv", tid, False)) {
sewardja8d8e232005-06-07 20:04:56 +00004909 SET_STATUS_Failure( VKI_EBADF );
jsgf855d93d2003-10-13 22:26:55 +00004910 } else {
njn22cfccb2004-11-27 16:10:23 +00004911 PRE_MEM_READ( "readv(vector)", ARG2, ARG3 * sizeof(struct vki_iovec) );
nethercoted6b5a212004-11-15 17:04:14 +00004912
njn22cfccb2004-11-27 16:10:23 +00004913 if (ARG2 != 0) {
nethercoted6b5a212004-11-15 17:04:14 +00004914 /* ToDo: don't do any of the following if the vector is invalid */
njn22cfccb2004-11-27 16:10:23 +00004915 vec = (struct vki_iovec *)ARG2;
4916 for (i = 0; i < (Int)ARG3; i++)
nethercoted6b5a212004-11-15 17:04:14 +00004917 PRE_MEM_WRITE( "readv(vector[...])",
4918 (Addr)vec[i].iov_base, vec[i].iov_len );
4919 }
jsgf855d93d2003-10-13 22:26:55 +00004920 }
4921}
4922
nethercote85a456f2004-11-16 17:31:56 +00004923POST(sys_readv)
jsgf855d93d2003-10-13 22:26:55 +00004924{
sewardja8d8e232005-06-07 20:04:56 +00004925 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00004926 if (RES > 0) {
jsgf855d93d2003-10-13 22:26:55 +00004927 Int i;
njn22cfccb2004-11-27 16:10:23 +00004928 struct vki_iovec * vec = (struct vki_iovec *)ARG2;
4929 Int remains = RES;
jsgf855d93d2003-10-13 22:26:55 +00004930
njn22cfccb2004-11-27 16:10:23 +00004931 /* RES holds the number of bytes read. */
4932 for (i = 0; i < (Int)ARG3; i++) {
jsgf855d93d2003-10-13 22:26:55 +00004933 Int nReadThisBuf = vec[i].iov_len;
4934 if (nReadThisBuf > remains) nReadThisBuf = remains;
nethercoteef0c7662004-11-06 15:38:43 +00004935 POST_MEM_WRITE( (Addr)vec[i].iov_base, nReadThisBuf );
jsgf855d93d2003-10-13 22:26:55 +00004936 remains -= nReadThisBuf;
4937 if (remains < 0) VG_(core_panic)("readv: remains < 0");
4938 }
4939 }
4940}
4941
sewardja8d8e232005-06-07 20:04:56 +00004942PRE(sys_rename)
jsgf855d93d2003-10-13 22:26:55 +00004943{
njn22cfccb2004-11-27 16:10:23 +00004944 PRINT("sys_rename ( %p, %p )", ARG1, ARG2 );
nethercote9a3beb92004-11-12 17:07:26 +00004945 PRE_REG_READ2(long, "rename", const char *, oldpath, const char *, newpath);
njn22cfccb2004-11-27 16:10:23 +00004946 PRE_MEM_RASCIIZ( "rename(oldpath)", ARG1 );
4947 PRE_MEM_RASCIIZ( "rename(newpath)", ARG2 );
jsgf855d93d2003-10-13 22:26:55 +00004948}
4949
sewardj78b50e42005-06-08 01:47:28 +00004950PRE(sys_rmdir)
4951{
4952 *flags |= SfMayBlock;
4953 PRINT("sys_rmdir ( %p )", ARG1);
4954 PRE_REG_READ1(long, "rmdir", const char *, pathname);
4955 PRE_MEM_RASCIIZ( "rmdir(pathname)", ARG1 );
4956}
4957
sewardja8d8e232005-06-07 20:04:56 +00004958PRE(sys_select)
jsgf855d93d2003-10-13 22:26:55 +00004959{
sewardja8d8e232005-06-07 20:04:56 +00004960 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00004961 PRINT("sys_select ( %d, %p, %p, %p, %p )", ARG1,ARG2,ARG3,ARG4,ARG5);
nethercotef1049bf2004-11-14 17:03:47 +00004962 PRE_REG_READ5(long, "select",
4963 int, n, vki_fd_set *, readfds, vki_fd_set *, writefds,
4964 vki_fd_set *, exceptfds, struct timeval *, timeout);
4965 // XXX: this possibly understates how much memory is read.
njn22cfccb2004-11-27 16:10:23 +00004966 if (ARG2 != 0)
nethercotef1049bf2004-11-14 17:03:47 +00004967 PRE_MEM_READ( "select(readfds)",
njn22cfccb2004-11-27 16:10:23 +00004968 ARG2, ARG1/8 /* __FD_SETSIZE/8 */ );
4969 if (ARG3 != 0)
nethercotef1049bf2004-11-14 17:03:47 +00004970 PRE_MEM_READ( "select(writefds)",
njn22cfccb2004-11-27 16:10:23 +00004971 ARG3, ARG1/8 /* __FD_SETSIZE/8 */ );
4972 if (ARG4 != 0)
nethercotef1049bf2004-11-14 17:03:47 +00004973 PRE_MEM_READ( "select(exceptfds)",
njn22cfccb2004-11-27 16:10:23 +00004974 ARG4, ARG1/8 /* __FD_SETSIZE/8 */ );
4975 if (ARG5 != 0)
4976 PRE_MEM_READ( "select(timeout)", ARG5, sizeof(struct vki_timeval) );
nethercotef1049bf2004-11-14 17:03:47 +00004977}
4978
sewardje6d5e722005-06-10 10:27:55 +00004979PRE(sys_setgid)
4980{
4981 PRINT("sys_setgid ( %d )", ARG1);
4982 PRE_REG_READ1(long, "setgid", vki_gid_t, gid);
4983}
sewardj696c5512005-06-08 23:38:32 +00004984
4985PRE(sys_setsid)
4986{
4987 PRINT("sys_setsid ( )");
4988 PRE_REG_READ0(long, "setsid");
4989}
4990
sewardje6d5e722005-06-10 10:27:55 +00004991PRE(sys_setgroups)
4992{
4993 PRINT("setgroups ( %llu, %p )", (ULong)ARG1, ARG2);
4994 PRE_REG_READ2(long, "setgroups", int, size, vki_gid_t *, list);
4995 if (ARG1 > 0)
4996 PRE_MEM_READ( "setgroups(list)", ARG2, ARG1 * sizeof(vki_gid_t) );
4997}
sewardj696c5512005-06-08 23:38:32 +00004998
4999PRE(sys_setpgid)
5000{
5001 PRINT("setpgid ( %d, %d )", ARG1, ARG2);
5002 PRE_REG_READ2(long, "setpgid", vki_pid_t, pid, vki_pid_t, pgid);
5003}
5004
5005PRE(sys_setregid)
5006{
5007 PRINT("sys_setregid ( %d, %d )", ARG1, ARG2);
5008 PRE_REG_READ2(long, "setregid", vki_gid_t, rgid, vki_gid_t, egid);
5009}
5010
sewardje6d5e722005-06-10 10:27:55 +00005011PRE(sys_setreuid)
5012{
5013 PRINT("sys_setreuid ( 0x%x, 0x%x )", ARG1, ARG2);
5014 PRE_REG_READ2(long, "setreuid", vki_uid_t, ruid, vki_uid_t, euid);
5015}
nethercote9c311eb2004-11-12 18:20:12 +00005016
sewardja8d8e232005-06-07 20:04:56 +00005017PRE(sys_setrlimit)
jsgf855d93d2003-10-13 22:26:55 +00005018{
njn22cfccb2004-11-27 16:10:23 +00005019 PRINT("sys_setrlimit ( %d, %p )", ARG1,ARG2);
nethercote17258dc2004-11-12 19:55:08 +00005020 PRE_REG_READ2(long, "setrlimit",
5021 unsigned int, resource, struct rlimit *, rlim);
njn22cfccb2004-11-27 16:10:23 +00005022 PRE_MEM_READ( "setrlimit(rlim)", ARG2, sizeof(struct vki_rlimit) );
fitzhardingeb50068f2004-02-24 23:42:55 +00005023
njn22cfccb2004-11-27 16:10:23 +00005024 if (ARG1 == VKI_RLIMIT_NOFILE) {
5025 if (((struct vki_rlimit *)ARG2)->rlim_cur > VG_(fd_hard_limit) ||
5026 ((struct vki_rlimit *)ARG2)->rlim_max != VG_(fd_hard_limit)) {
sewardja8d8e232005-06-07 20:04:56 +00005027 SET_STATUS_Failure( VKI_EPERM );
thughesad1c9562004-06-26 11:27:52 +00005028 }
5029 else {
njn22cfccb2004-11-27 16:10:23 +00005030 VG_(fd_soft_limit) = ((struct vki_rlimit *)ARG2)->rlim_cur;
sewardja8d8e232005-06-07 20:04:56 +00005031 SET_STATUS_Success( 0 );
thughesad1c9562004-06-26 11:27:52 +00005032 }
5033 }
njn22cfccb2004-11-27 16:10:23 +00005034 else if (ARG1 == VKI_RLIMIT_DATA) {
5035 if (((struct vki_rlimit *)ARG2)->rlim_cur > ((struct vki_rlimit *)ARG2)->rlim_max ||
5036 ((struct vki_rlimit *)ARG2)->rlim_max > ((struct vki_rlimit *)ARG2)->rlim_max) {
sewardja8d8e232005-06-07 20:04:56 +00005037 SET_STATUS_Failure( VKI_EPERM );
thughesaa4fb112004-09-11 14:19:25 +00005038 }
5039 else {
njn22cfccb2004-11-27 16:10:23 +00005040 VG_(client_rlimit_data) = *(struct vki_rlimit *)ARG2;
sewardja8d8e232005-06-07 20:04:56 +00005041 SET_STATUS_Success( 0 );
thughesaa4fb112004-09-11 14:19:25 +00005042 }
fitzhardingeb50068f2004-02-24 23:42:55 +00005043 }
njn22cfccb2004-11-27 16:10:23 +00005044 else if (ARG1 == VKI_RLIMIT_STACK && tid == 1) {
5045 if (((struct vki_rlimit *)ARG2)->rlim_cur > ((struct vki_rlimit *)ARG2)->rlim_max ||
5046 ((struct vki_rlimit *)ARG2)->rlim_max > ((struct vki_rlimit *)ARG2)->rlim_max) {
sewardja8d8e232005-06-07 20:04:56 +00005047 SET_STATUS_Failure( VKI_EPERM );
thughesc37184f2004-09-11 14:16:57 +00005048 }
5049 else {
sewardja8d8e232005-06-07 20:04:56 +00005050 VG_(threads)[tid].client_stack_szB = ((struct vki_rlimit *)ARG2)->rlim_cur;
njn22cfccb2004-11-27 16:10:23 +00005051 VG_(client_rlimit_stack) = *(struct vki_rlimit *)ARG2;
sewardja8d8e232005-06-07 20:04:56 +00005052 SET_STATUS_Success( 0 );
thughesc37184f2004-09-11 14:16:57 +00005053 }
5054 }
jsgf855d93d2003-10-13 22:26:55 +00005055}
5056
sewardje6d5e722005-06-10 10:27:55 +00005057PRE(sys_setuid)
5058{
5059 PRINT("sys_setuid ( %d )", ARG1);
5060 PRE_REG_READ1(long, "setuid", vki_uid_t, uid);
5061}
jsgf855d93d2003-10-13 22:26:55 +00005062
sewardj696c5512005-06-08 23:38:32 +00005063PRE(sys_newstat)
5064{
5065 PRINT("sys_newstat ( %p(%s), %p )", ARG1,ARG1,ARG2);
5066 PRE_REG_READ2(long, "stat", char *, file_name, struct stat *, buf);
5067 PRE_MEM_RASCIIZ( "stat(file_name)", ARG1 );
5068 PRE_MEM_WRITE( "stat(buf)", ARG2, sizeof(struct vki_stat) );
5069}
5070
5071POST(sys_newstat)
5072{
5073 POST_MEM_WRITE( ARG2, sizeof(struct vki_stat) );
5074}
5075
5076PRE(sys_statfs)
5077{
5078 PRINT("sys_statfs ( %p, %p )",ARG1,ARG2);
5079 PRE_REG_READ2(long, "statfs", const char *, path, struct statfs *, buf);
5080 PRE_MEM_RASCIIZ( "statfs(path)", ARG1 );
5081 PRE_MEM_WRITE( "statfs(buf)", ARG2, sizeof(struct vki_statfs) );
5082}
sewardj696c5512005-06-08 23:38:32 +00005083POST(sys_statfs)
5084{
5085 POST_MEM_WRITE( ARG2, sizeof(struct vki_statfs) );
5086}
5087
sewardje6d5e722005-06-10 10:27:55 +00005088PRE(sys_statfs64)
5089{
5090 PRINT("sys_statfs64 ( %p, %llu, %p )",ARG1,(ULong)ARG2,ARG3);
5091 PRE_REG_READ3(long, "statfs64",
5092 const char *, path, vki_size_t, size, struct statfs64 *, buf);
5093 PRE_MEM_RASCIIZ( "statfs64(path)", ARG1 );
5094 PRE_MEM_WRITE( "statfs64(buf)", ARG3, ARG2 );
5095}
5096POST(sys_statfs64)
5097{
5098 POST_MEM_WRITE( ARG3, ARG2 );
5099}
sewardj78b50e42005-06-08 01:47:28 +00005100
5101PRE(sys_symlink)
5102{
5103 *flags |= SfMayBlock;
5104 PRINT("sys_symlink ( %p, %p )",ARG1,ARG2);
5105 PRE_REG_READ2(long, "symlink", const char *, oldpath, const char *, newpath);
5106 PRE_MEM_RASCIIZ( "symlink(oldpath)", ARG1 );
5107 PRE_MEM_RASCIIZ( "symlink(newpath)", ARG2 );
5108}
sewardj9efbbef2005-03-01 16:45:23 +00005109
sewardja8d8e232005-06-07 20:04:56 +00005110PRE(sys_time)
jsgf855d93d2003-10-13 22:26:55 +00005111{
5112 /* time_t time(time_t *t); */
njn22cfccb2004-11-27 16:10:23 +00005113 PRINT("sys_time ( %p )",ARG1);
nethercotec6851dd2004-11-11 18:00:47 +00005114 PRE_REG_READ1(long, "time", int *, t);
njn22cfccb2004-11-27 16:10:23 +00005115 if (ARG1 != 0) {
5116 PRE_MEM_WRITE( "time(t)", ARG1, sizeof(vki_time_t) );
jsgf855d93d2003-10-13 22:26:55 +00005117 }
5118}
5119
nethercote85a456f2004-11-16 17:31:56 +00005120POST(sys_time)
jsgf855d93d2003-10-13 22:26:55 +00005121{
njn22cfccb2004-11-27 16:10:23 +00005122 if (ARG1 != 0) {
5123 POST_MEM_WRITE( ARG1, sizeof(vki_time_t) );
jsgf855d93d2003-10-13 22:26:55 +00005124 }
5125}
5126
sewardj78b50e42005-06-08 01:47:28 +00005127PRE(sys_times)
5128{
5129 PRINT("sys_times ( %p )", ARG1);
5130 PRE_REG_READ1(long, "times", struct tms *, buf);
tom18f19272005-07-18 11:03:35 +00005131 if (ARG1 != 0) {
5132 PRE_MEM_WRITE( "times(buf)", ARG1, sizeof(struct vki_tms) );
5133 }
sewardj78b50e42005-06-08 01:47:28 +00005134}
5135
5136POST(sys_times)
5137{
5138 if (ARG1 != 0) {
5139 POST_MEM_WRITE( ARG1, sizeof(struct vki_tms) );
5140 }
5141}
5142
5143PRE(sys_umask)
5144{
5145 PRINT("sys_umask ( %d )", ARG1);
5146 PRE_REG_READ1(long, "umask", int, mask);
5147}
jsgf855d93d2003-10-13 22:26:55 +00005148
sewardja8d8e232005-06-07 20:04:56 +00005149PRE(sys_unlink)
jsgf855d93d2003-10-13 22:26:55 +00005150{
sewardja8d8e232005-06-07 20:04:56 +00005151 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00005152 PRINT("sys_unlink ( %p(%s) )", ARG1,ARG1);
nethercotec6851dd2004-11-11 18:00:47 +00005153 PRE_REG_READ1(long, "unlink", const char *, pathname);
njn22cfccb2004-11-27 16:10:23 +00005154 PRE_MEM_RASCIIZ( "unlink(pathname)", ARG1 );
jsgf855d93d2003-10-13 22:26:55 +00005155}
5156
sewardja8d8e232005-06-07 20:04:56 +00005157PRE(sys_newuname)
jsgf855d93d2003-10-13 22:26:55 +00005158{
njn22cfccb2004-11-27 16:10:23 +00005159 PRINT("sys_newuname ( %p )", ARG1);
nethercote1a1b9b72004-11-12 11:19:36 +00005160 PRE_REG_READ1(long, "uname", struct new_utsname *, buf);
njn22cfccb2004-11-27 16:10:23 +00005161 PRE_MEM_WRITE( "uname(buf)", ARG1, sizeof(struct vki_new_utsname) );
jsgf855d93d2003-10-13 22:26:55 +00005162}
5163
nethercote85a456f2004-11-16 17:31:56 +00005164POST(sys_newuname)
jsgf855d93d2003-10-13 22:26:55 +00005165{
njn22cfccb2004-11-27 16:10:23 +00005166 if (ARG1 != 0) {
5167 POST_MEM_WRITE( ARG1, sizeof(struct vki_new_utsname) );
jsgf855d93d2003-10-13 22:26:55 +00005168 }
5169}
5170
sewardja8d8e232005-06-07 20:04:56 +00005171PRE(sys_waitpid)
jsgf855d93d2003-10-13 22:26:55 +00005172{
sewardja8d8e232005-06-07 20:04:56 +00005173 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00005174 PRINT("sys_waitpid ( %d, %p, %d )", ARG1,ARG2,ARG3);
nethercotec6851dd2004-11-11 18:00:47 +00005175 PRE_REG_READ3(long, "waitpid",
5176 vki_pid_t, pid, unsigned int *, status, int, options);
jsgf855d93d2003-10-13 22:26:55 +00005177
njn22cfccb2004-11-27 16:10:23 +00005178 if (ARG2 != (Addr)NULL)
5179 PRE_MEM_WRITE( "waitpid(status)", ARG2, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00005180}
5181
nethercote85a456f2004-11-16 17:31:56 +00005182POST(sys_waitpid)
jsgf855d93d2003-10-13 22:26:55 +00005183{
njn22cfccb2004-11-27 16:10:23 +00005184 if (ARG2 != (Addr)NULL)
5185 POST_MEM_WRITE( ARG2, sizeof(int) );
jsgf855d93d2003-10-13 22:26:55 +00005186}
5187
sewardja8d8e232005-06-07 20:04:56 +00005188PRE(sys_wait4)
jsgf855d93d2003-10-13 22:26:55 +00005189{
sewardja8d8e232005-06-07 20:04:56 +00005190 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00005191 PRINT("sys_wait4 ( %d, %p, %d, %p )", ARG1,ARG2,ARG3,ARG4);
jsgf855d93d2003-10-13 22:26:55 +00005192
nethercote7f7e4d12004-11-15 12:28:58 +00005193 PRE_REG_READ4(long, "wait4",
5194 vki_pid_t, pid, unsigned int *, status, int, options,
5195 struct rusage *, rusage);
njn22cfccb2004-11-27 16:10:23 +00005196 if (ARG2 != (Addr)NULL)
5197 PRE_MEM_WRITE( "wait4(status)", ARG2, sizeof(int) );
5198 if (ARG4 != (Addr)NULL)
5199 PRE_MEM_WRITE( "wait4(rusage)", ARG4, sizeof(struct vki_rusage) );
jsgf855d93d2003-10-13 22:26:55 +00005200}
5201
nethercote85a456f2004-11-16 17:31:56 +00005202POST(sys_wait4)
jsgf855d93d2003-10-13 22:26:55 +00005203{
njn22cfccb2004-11-27 16:10:23 +00005204 if (ARG2 != (Addr)NULL)
5205 POST_MEM_WRITE( ARG2, sizeof(int) );
5206 if (ARG4 != (Addr)NULL)
5207 POST_MEM_WRITE( ARG4, sizeof(struct vki_rusage) );
jsgf855d93d2003-10-13 22:26:55 +00005208}
5209
sewardja8d8e232005-06-07 20:04:56 +00005210PRE(sys_writev)
jsgf855d93d2003-10-13 22:26:55 +00005211{
jsgf855d93d2003-10-13 22:26:55 +00005212 Int i;
nethercote73b526f2004-10-31 18:48:21 +00005213 struct vki_iovec * vec;
sewardja8d8e232005-06-07 20:04:56 +00005214 *flags |= SfMayBlock;
njn22cfccb2004-11-27 16:10:23 +00005215 PRINT("sys_writev ( %d, %p, %llu )",ARG1,ARG2,(ULong)ARG3);
nethercoted6b5a212004-11-15 17:04:14 +00005216 PRE_REG_READ3(ssize_t, "writev",
5217 unsigned long, fd, const struct iovec *, vector,
5218 unsigned long, count);
sewardj7eb7c582005-06-23 01:02:53 +00005219 if (!ML_(fd_allowed)(ARG1, "writev", tid, False)) {
sewardja8d8e232005-06-07 20:04:56 +00005220 SET_STATUS_Failure( VKI_EBADF );
jsgf855d93d2003-10-13 22:26:55 +00005221 } else {
nethercoteef0c7662004-11-06 15:38:43 +00005222 PRE_MEM_READ( "writev(vector)",
njn22cfccb2004-11-27 16:10:23 +00005223 ARG2, ARG3 * sizeof(struct vki_iovec) );
5224 if (ARG2 != 0) {
nethercoted6b5a212004-11-15 17:04:14 +00005225 /* ToDo: don't do any of the following if the vector is invalid */
njn22cfccb2004-11-27 16:10:23 +00005226 vec = (struct vki_iovec *)ARG2;
5227 for (i = 0; i < (Int)ARG3; i++)
nethercoted6b5a212004-11-15 17:04:14 +00005228 PRE_MEM_READ( "writev(vector[...])",
5229 (Addr)vec[i].iov_base, vec[i].iov_len );
5230 }
jsgf855d93d2003-10-13 22:26:55 +00005231 }
5232}
5233
sewardje6d5e722005-06-10 10:27:55 +00005234PRE(sys_utimes)
5235{
5236 PRINT("sys_utimes ( %p, %p )", ARG1,ARG2);
5237 PRE_REG_READ2(long, "utimes", char *, filename, struct timeval *, tvp);
5238 PRE_MEM_RASCIIZ( "utimes(filename)", ARG1 );
5239 if (ARG2 != 0)
5240 PRE_MEM_READ( "utimes(tvp)", ARG2, sizeof(struct vki_timeval) );
5241}
5242
sewardj696c5512005-06-08 23:38:32 +00005243PRE(sys_acct)
5244{
5245 PRINT("sys_acct ( %p )", ARG1);
5246 PRE_REG_READ1(long, "acct", const char *, filename);
5247 PRE_MEM_RASCIIZ( "acct(filename)", ARG1 );
5248}
muellerd3502b62003-11-19 00:43:57 +00005249
sewardja8d8e232005-06-07 20:04:56 +00005250PRE(sys_pause)
thughes2f8d5f82004-09-11 14:29:19 +00005251{
sewardja8d8e232005-06-07 20:04:56 +00005252 *flags |= SfMayBlock;
nethercote0df495a2004-11-11 16:38:21 +00005253 PRINT("sys_pause ( )");
5254 PRE_REG_READ0(long, "pause");
jsgf855d93d2003-10-13 22:26:55 +00005255}
5256
sewardja8d8e232005-06-07 20:04:56 +00005257//zz // XXX: x86-specific
5258//zz PRE(sys_sigsuspend, SfMayBlock)
5259//zz {
5260//zz /* The C library interface to sigsuspend just takes a pointer to
5261//zz a signal mask but this system call has three arguments - the first
5262//zz two don't appear to be used by the kernel and are always passed as
5263//zz zero by glibc and the third is the first word of the signal mask
5264//zz so only 32 signals are supported.
5265//zz
5266//zz In fact glibc normally uses rt_sigsuspend if it is available as
5267//zz that takes a pointer to the signal mask so supports more signals.
5268//zz */
5269//zz PRINT("sys_sigsuspend ( %d, %d, %d )", ARG1,ARG2,ARG3 );
5270//zz PRE_REG_READ3(int, "sigsuspend",
5271//zz int, history0, int, history1,
5272//zz vki_old_sigset_t, mask);
5273//zz }
jsgf855d93d2003-10-13 22:26:55 +00005274
nethercotea3a2c142004-11-14 14:13:05 +00005275// XXX: x86-specific
sewardja8d8e232005-06-07 20:04:56 +00005276PRE(sys_sigaltstack)
jsgf855d93d2003-10-13 22:26:55 +00005277{
njn22cfccb2004-11-27 16:10:23 +00005278 PRINT("sigaltstack ( %p, %p )",ARG1,ARG2);
nethercoteb77dee62004-11-16 17:13:24 +00005279 PRE_REG_READ2(int, "sigaltstack",
5280 const vki_stack_t *, ss, vki_stack_t *, oss);
njn22cfccb2004-11-27 16:10:23 +00005281 if (ARG1 != 0) {
tom92098db2005-07-18 23:18:10 +00005282 const vki_stack_t *ss = (vki_stack_t *)ARG1;
5283 PRE_MEM_READ( "sigaltstack(ss)", (Addr)&ss->ss_sp, sizeof(ss->ss_sp) );
5284 PRE_MEM_READ( "sigaltstack(ss)", (Addr)&ss->ss_flags, sizeof(ss->ss_flags) );
5285 PRE_MEM_READ( "sigaltstack(ss)", (Addr)&ss->ss_size, sizeof(ss->ss_size) );
jsgf855d93d2003-10-13 22:26:55 +00005286 }
njn22cfccb2004-11-27 16:10:23 +00005287 if (ARG2 != 0) {
5288 PRE_MEM_WRITE( "sigaltstack(oss)", ARG2, sizeof(vki_stack_t) );
jsgf855d93d2003-10-13 22:26:55 +00005289 }
5290
sewardja8d8e232005-06-07 20:04:56 +00005291 SET_STATUS_from_SysRes(
5292 VG_(do_sys_sigaltstack) (tid, (vki_stack_t*)ARG1,
5293 (vki_stack_t*)ARG2)
5294 );
jsgf855d93d2003-10-13 22:26:55 +00005295}
nethercote85a456f2004-11-16 17:31:56 +00005296POST(sys_sigaltstack)
jsgf855d93d2003-10-13 22:26:55 +00005297{
sewardja8d8e232005-06-07 20:04:56 +00005298 vg_assert(SUCCESS);
njn22cfccb2004-11-27 16:10:23 +00005299 if (RES == 0 && ARG2 != 0)
5300 POST_MEM_WRITE( ARG2, sizeof(vki_stack_t));
jsgf855d93d2003-10-13 22:26:55 +00005301}
5302
sewardje6d5e722005-06-10 10:27:55 +00005303#undef PRE
5304#undef POST
sewardj2e93c502002-04-12 11:12:52 +00005305
sewardjde4a1d02002-03-22 01:27:54 +00005306/*--------------------------------------------------------------------*/
njnc1b01812005-06-17 22:19:06 +00005307/*--- end ---*/
sewardjde4a1d02002-03-22 01:27:54 +00005308/*--------------------------------------------------------------------*/
sewardj45f4e7c2005-09-27 19:20:21 +00005309